《Learning Advanced JavaScript》学习总结

一个让我收益匪浅的教程。用这篇博文对一些关键知识点进行整理。
教程地址:https://johnresig.com/apps/learn/

1.goal

// The .bind method from Prototype.js 
Function.prototype.bind = function(){ 
  var fn = this, args = Array.prototype.slice.call(arguments), object = args.shift(); 
  return function(){ 
    return fn.apply(object, 
      args.concat(Array.prototype.slice.call(arguments))); 
  }; 
};

2.ways to define function

function fn(){}
var fn= function(){}
obj.fn = function(){}

  • order is no a matter(define promotion)
    function can be defined below return//次序不重要

  • We can refer to a function, within itself, by its name(iteration)//函数内可以调用函数自身

3.What is the name of a function?

var fn= function doSth(){}这种形式定义的函数,在全局中只能以fn为名来调用。

var ninja = function myNinja(){ 
  assert( ninja == myNinja, "This function is named two things - at once!" ); 
}; 
ninja(); 
assert( typeof myNinja == "undefined", "But myNinja isn't defined outside of the function." ); 

3.1 the function which is an object property can run & what about the property removed.

匿名函数作为对属性时,不会被声明,只在被调用时执行。因而当对应属性被删除时,再调用该函数则无效。

var ninja = { 
  yell: function(n){ 
    return n > 0 ? ninja.yell(n-1) + "a" : "hiy"; 
  } 
}; 
assert( ninja.yell(4) == "hiyaaaa", "A single object isn't too bad, either." );
var samurai = { yell: ninja.yell }; 
var ninja = null; 
 
try { 
  samurai.yell(4); 
} catch(e){ 
  assert( false, "Uh, this isn't good! Where'd ninja.yell go?" ); 
}

3.2give the anonymous function a name

当属性中的函数具名时,在属性被创建并赋值时,便声明了以属性键名为名的函数。及时属性之后被清空,函数依然存在。

var ninja = { 
  yell: function yell(n){ 
    return n > 0 ? yell(n-1) + "a" : "hiy"; 
  } 
}; 
assert( ninja.yell(4) == "hiyaaaa", "Works as we would expect it to!" ); 
 
var samurai = { yell: ninja.yell }; 
var ninja = {}; 
assert( samurai.yell(4) == "hiyaaaa", "The method correctly calls itself." );

3.3What if we don't want to give the function a name?

在匿名函数中,可以用arguments.callee调用函数自身

var ninja = {
  yell: function(n){
    return n > 0 ? arguments.callee(n-1) + "a" : "hiy";
  }
};
assert( ninja.yell(4) == "hiyaaaa", "arguments.callee is the function itself." );

4 Functions as Objects

4.1 Is it possible to cache the return results from a function

函数作为一个对象,可以在其子对象中进行数据缓存。

function isPrime( num ) { 
  if ( isPrime.cache[ num ] != null ) 
    return isPrime.cache[ num ]; //If the parm cached,return corresponding result
   
  var prime = num != 1; // Everything but 1 can be prime 
  for ( var i = 2; i < num; i++ ) { 
    if ( num % i == 0 ) { 
      prime = false; 
      break; 
    } 
  } 
  
  isPrime.cache[ num ] = prime //cached the parm&result
  
  return prime; 
} 
 
isPrime.cache = {}; 
 
assert( isPrime(5), "Make sure the function works, 5 is prime." ); 
assert( isPrime.cache[5], "Make sure the answer is cached." ); 

5.Context

5.1How can we change the context of a function

改变上下文的方法

var object = {}; 
function fn(){ 
  return this; 
} 
assert( fn() == this, "The context is the global object." ); 
assert( fn.call(object) == object, "The context is changed to a specific object." );

.call()&.apply()也可以使用

5.2What does the new operator do?

new操作符做了什么
1.创建一个空对象作为this
2.this.proto指向构造函数的prototype
3.运行构造函数
4.返回this(如果函数没有return)

function Ninja(name){
  this.changeName = function(name){
    this.name = name;
  };

  this.changeName( name );
}

var ninja = new Ninja("John");
assert( ninja.name == "John", "The name has been set on initialization" );//function(name) has been implemented

ninja.changeName("Bob");

5.3 How to make sure that the new operator is always used

function User(first, last){
  if ( !(this instanceof User) )
    return new User(first, last);
  
  this.name = first + " " + last;
}

var name = "Resig";
var user = User("John", name);

assert( user, "This was defined correctly, even if it was by mistake." );
assert( name == "Resig", "The right name was maintained." );

5.4Flexible Arguments

Array-like object can implement method of Array by change context
Math.max/Math.min/sort/slice/splice

Closures

  • Closures are frequently used for callbacks/event listener/timer
  • Private properties, using closures.

Instance Type

instance.construtor

Inheritance

prototypes

Extending prototypes can be dangerous.

Object.prototype.keys = function(){
  var keys = [];
  for ( var i in this )
    keys.push( i );
  return keys;
};

var obj = { a: 1, b: 2, c: 3 };

assert( obj.keys().length == 3, "We should only have 3 properties." );

delete Object.prototype.keys;

对数组进行拓展后,for in遍历将失效,多出一项拓展函数。
因为for in 会枚举原型链上的所有属性。

Enforcing Function Context

当我们在click handler上绑定一个对象方法时。因为使用对象调用函数时,this指向该对象,所以会发生如下错误。

var Button = {
  click: function(){
    this.clicked = true;
  }
};

var elem = document.createElement("li");
elem.innerHTML = "Click me!";
elem.onclick = Button.click;
document.getElementById("results").appendChild(elem);

elem.onclick();
assert( elem.clicked, "The clicked property was accidentally set on the element" );

我们需要将context指向正确的地方

function bind(context, name){
  return function(){
    return context[name].apply(context, arguments);
  };
}

var Button = {
  click: function(){
    this.clicked = true;
  }
};

var elem = document.createElement("li");
elem.innerHTML = "Click me!";
elem.onclick = bind(Button, "click");
document.getElementById("results").appendChild(elem);

elem.onclick();
assert( Button.clicked, "The clicked property was correctly set on the object" );

这种绑定方法可以直接写入原型链中进行调用

Function.prototype.bind = function(object){
  var fn = this;
  return function(){
    return fn.apply(object, arguments);
  };
};//将对象方法变成一个绑定context的函数。

var Button = {
  click: function(){
    this.clicked = true;
  }
};

var elem = document.createElement("li");
elem.innerHTML = "Click me!";
elem.onclick = Button.click.bind(Button);
document.getElementById("results").appendChild(elem);

elem.onclick();
assert( Button.clicked, "The clicked property was correctly set on the object" );
Function.prototype.bind = function(){
  var fn = this, args = Array.prototype.slice.call(arguments), object = args.shift();//object作为context
  return function(){
    return fn.apply(object,
      args.concat(Array.prototype.slice.call(arguments)));
  };//将fn所需的参数提前以供使用,同时保留bind时使用的参数。
};

var Button = {
  click: function(value){
    this.clicked = value;
  }
};

var elem = document.createElement("li");
elem.innerHTML = "Click me!";
elem.onclick = Button.click.bind(Button, false);
document.getElementById("results").appendChild(elem);

elem.onclick();
assert( Button.clicked === false, "The clicked property was correctly set on the object" );

Function Length

方程的length等于参数的个数

Function overloading

根据参数的个数,调用不同的方法。

function addMethod(object, name, fn){
  // Save a reference to the old method
  var old = object[ name ];

  // Overwrite the method with our new one
  object[ name ] = function(){
    // Check the number of incoming arguments,
    // compared to our overloaded function
    if ( fn.length == arguments.length )
      // If there was a match, run the function
      return fn.apply( this, arguments );

    // Otherwise, fallback to the old method
    else if ( typeof old === "function" )
      return old.apply( this, arguments );
  };
}

这个策略中,新方法存储在封包函数中,旧方法作为封包的环境。封包函数根据参数个数来决定调用新旧、方法。类似的封包函数作为旧方法不断被调用,直至参数个数符合后,执行对应方法。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,366评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,521评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,689评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,925评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,942评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,727评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,447评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,349评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,820评论 1 317
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,990评论 3 337
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,127评论 1 351
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,812评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,471评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,017评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,142评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,388评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,066评论 2 355

推荐阅读更多精彩内容

  • 以下翻译自Apple官方文档,结合自己的理解记录下来。翻译基于 swift 3.0.1 原文地址 Closure...
    艺术农阅读 1,539评论 0 3
  • //Clojure入门教程: Clojure – Functional Programming for the J...
    葡萄喃喃呓语阅读 3,672评论 0 7
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,667评论 18 139
  • 今天介绍“抖”字。千万别小看这个字,以及同类的字。“抖”字左右都有横,也都有竖,对于同类笔画,假如位置关系处理不妥...
    晓暐阅读 500评论 1 2
  • 登高望远,可见远景连天;闭目望心,可察心池是否纯蓝。执心谦冲,不自盈大,是古训,穷者理所应当,达者同样必要。哲人指...
    古月青阅读 1,491评论 13 12