JavaScript语言精华

精华 #

我相信我精雕细琢出来的优雅子集大大地优于这门语言的整体,它更可靠、更易读、更易于维护。

浏览器API和DOM相当糟糕,连累了JavaScript。写一本DOM的精华的书是一项不可能完成的任务。

JavaScript中优秀的想法包括函数、弱类型、动态对象和富有变现力的对象字面量表示法。糟粕的想法包括基于全局变量的编程模型。

对象 #

JavaScript包含一种原型链的特性,允许对象继承另一个对象的属性。

原型 #

每个对象都连接到一个原型对象,并可以从中继承属性。对象字面量创建的对象都连接到Object.prototype,它是JavaScript中过的标配对象。

函数 #

函数对象 #

函数也是对象,对象字面量创建的对象连接到Object.prototype,函数对象连接到Function.prototype,而它又连接到Object.prototype

函数字面量 #

通过函数字面量创建的函数对象包含一个连到外部上下文的连接。这被称为闭包(closure)。

调用 #

除了声明时定义的形式参数,每个函数还接收两个附加的参数:this和arguments。

this的值取决于调用的模式。有4中调用模式:方法、函数、构造器、apply。

方法调用模式 #

函数被作为一个对象的属性,就教方法。此时this为该对象。

函数调用模式 #

函数没有作为对象的属性,他就被当作一个函数调用了。此模式this被绑定到全局变量。

如果在一个方法内,又定义了一个函数,而这个函数中使用了this,那么这个this就是指向的全局变量。这是一个语言设计错误,正确的设计应该是指向方法中的this。有一个容易的解决方案:将方法中的一个变量赋值为this,函数中访问变量即可。

1
2
3
4
5
6
7
myObject.double = function(){
  var that = this;
  var helper = function(){
    that.value = add(that.value, that.value)
  }
  helper();
}

helper 函数中如果使用 this 这个 this 就是指向全局变量。

构造器调用模式 #

JavaScript是一门基于原型继承的语言,这意味这一个对象可以从另一个对象继承属性。该语言是无类型的。(es6呢?)

new 调用一个函数,会创建一个连接到该函数的 prototype 成员的新对象,同时将 this 绑定到那个新对象上。这就是构造器调用。

Apply调用模式 #

因为JavaScript是一门函数式的面向对象语言,所以函数可以拥有方法。

apply 方法接受2个参数,绑定的 this ,和参数数组。

1
2
var array = [2, 4];
var sum  = add.apply(null, array);

闭包 #

一个函数可以访问它被创建时的上下文环境就叫闭包。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
var myObject = (function(){
  var value = 0;
  return {
    increment: function(inc){
      value += typeof inc === 'number' ? inc : 1;
    },
    getValue: function(){
      return value;
    }
  }
})()

原理: 函数作用域链:当函数被定义时,它会创建一个作用域链。作用域链是一个指向外部函数的变量对象的列表。这意味着在函数内部,可以访问所有外部函数及全局作用域中的变量。 闭包的产生:当一个函数内部定义了另一个函数,并且内部函数引用了外部函数的变量时,就形成了闭包。由于内部函数保持对外部函数作用域的引用,即使外部函数执行完毕后,内部函数仍然可以访问外部函数的变量,因此这些变量不会被销毁,形成了闭包。

incermentgetValue 两个函数被创建的上下文中有一个 value 变量。这两个函数可以访问 value ,这就叫 闭包