深入理解JavaScript系列(10)进阶

原型链

原型链是一个由对象组成的有限对象链,用于实现共享与继承。

var a = {
    x : 10,
    cal : function (z) {
        return this.x + this.y + z;
    }
}

var b = {
    y : 20,
    __proto__ : a
}

var c = {
    y : 30, 
    __proto__ : a
}

b.cal(30); // 60

对象通过隐式属性proto来实现继承。在继承机制中,this一直指向原本对象。如上对象a的proto的值为Object.prototype,而Object.prototype的proto的值为null

构造函数

function Foo(y) { //构造函数
    this.y = y;
}

Foo.prototype.x = 10;

Function.prototype.cal = function (z) {
    return this.x + this.y + z;
}

var b = new Foo(20)
var c = new Foo(30)

原型链如下:

b的显示属性为y,隐式属性__proto__指向Foo.prototype;
c的显示属性为y, 隐式属性__proto__指向Foo.prototype;
Foo.prototype.constructor 指向Foo;
Foo.prototype有x,cal显示属性;
Foo.prototype.__proto__为Object.prototype;// 即为 空对象:{}
object.prototype.__proto__为null
Foo.__proto__为Function.prototype //为 Empty 的值。
Function.prototype为Object.prototype

上下文栈(EC stack--execution context stack)

ECMAscript中代码有三种类型:global, function, eval;一个function可能产生无限的上下文环境。(一个函数的调用就可以产生一个新的上下文)。

function foo(bar){};
foo(10);
foo(20);
foo(30); //三次调用,三个上下文堆栈。

激活其上下文的某个上下文为调用者(caller),被激活的上下文为被调用者(callee)。被调用者也可能是调用者(调用自身)。

一个caller集火那个callee, caller就会暂停自身执行,然后控制权给callee。这个callee放入堆栈,成为进行的上下文。callee上下文结束后卫caller。callee可以通过retrun 与 抛出异常结束上下文。

上下文 Execution Context 上下文可以看做一个对象object,包括变量对象(variable object),this指针(this value), 作用域链(scope chain)。

变量对象是与执行上下文相关的数据作用域。函数表达式不包括在VO中。使用eval时候会使用新的上下文。使用全局或者调用者的变量。在一个函数中,VO被称为AO,activation object。

作用域链与原型链类似。作用域链是一个对象列表,用以检索上下文出现的标识符。可以理解为变量名称函数名称。普通参数。一个变量若没在函数内声明,则称为自由变量。

一般情况下,一个作用域链包括父级变量对象、自身变量对象、活动对象。但有时会在执行期间,动态加入作用域链(width、catch语句)。

Object.prototype.x = 10;
var w = 20;
var y = 30;

console.log(x) //10

(function foo (){
    var w = 40;
    var x = 100;
    with({z:50}) {
        console.log(w, x, y, z) // 40 10 30 50
        //x 是从 Object.prototype拿到。
        //因为{z : 50}是从它那里继承。
    }

    console.log(x, w) // 100, 40
}())

闭包(closures)

闭包是一些列代码块,并且静态保存所有父级作用域。 js为静态作用域。

function foo () {
    var x =10;
    return function bar() {
        console.log(x);
    }
}

var returnFunc = foo();
var x =20;
returnFunc(); // 10



var x = 10;
function foo () {
    console.log(x);
}

(function (fc) {
    var x = 20;
    fc(); // 10 foo函数中保存着全局变量x,而不是caller的作用域x。
}(foo))

this

this是上下文对象。它是执行上下文环境的一个属性,而不是某个变量对象的属性。它有caller提供。

function foo () {
    console.log(this);
}

foo(); //this

var bar = {baz : foo};

bar.baz() //bar
(bar.baz)() //bar----------------------不明白
(bar.baz = bar.baz)(); //全局
(false || bar.baz) () //全局
(bar.baz, bar.baz)()

var otherFoo = bar.baz;
otherFoo() //全局

this这个最后不是很明白。需要解决

Written on June 19, 2015