一.从原型到原型链
1.一切对象都是通过new函数实例化出来的
2. proto指向的是构造出自己的构造函数的原型
person.__proto__ === Person.prototype
补充:
1.constructor属性:
person.constructor === Person // true
当获取person.constructor时,其实就是person中并没有constructor属性,当不能读取到constructor属性时,会从person的原型,也就是Person.prototype中读取
2.__proto__
实际上它并不存在于Person.prototype中,它是来源于Object.prototype,与其说是一个属性,不如说是一个getter/setter,当使用obj.__proto__时,可以理解成返回了Object.getPrototypeOf(obj);
二. 作用域和动态作用域
注意点: 当执行一个函数的时候,就会创建一个执行上下文,并且压入执行上下文栈,当“函数执行完毕”的时候,就会将函数的执行上下文从栈中弹出。
var scope = "global scope";
function checkscope(){
var scope = "local scope";
function f(){
return scope;
}
return f();
}
checkscope();
var scope = "global scope";
function checkscope(){
var scope = "local scope";
function f(){
return scope;
}
return f;
}
checkscope()();
两段代码执行的结果一样,但是两端代码究竟有哪些不同呢?
代码执行过程模拟:
1.
ECstack.push(<checkscope> functionContext);
ECstack.push(<f> functionContext);
ECstack.pop()
ECstack.pop()
2.
ECstack.push(<checkscope> functionContext);
ECstack.pop()
ECstack.push(<f> functionContext);
ECstack.pop()
总结:二者的区别就是在于函数是否执行完毕,如果函数执行完毕就会立即将函数的执行上下文从栈中弹出。
--------------------------------------
var scope = "global scope";
function checkscope(){
var scope = "local scope";
function f(){
return scope;
}
return f;
}
var foo = checkscope();
foo();
这里直接给出简要的执行过程:
1.进入全局代码,创建全局执行上下文,全局执行上下文压入执行上下文栈
2.全局执行上下文初始化
3.执行 checkscope 函数,创建 checkscope 函数执行上下文,checkscope 执行上下文被压入执行上下文栈
4.checkscope 执行上下文初始化,创建变量对象、作用域链、this等
5.checkscope 函数执行完毕,checkscope 执行上下文从执行上下文栈中弹出
6.执行 f 函数,创建 f 函数执行上下文,f 执行上下文被压入执行上下文栈
7.f 执行上下文初始化,创建变量对象、作用域链、this等
8.f 函数执行完毕,f 函数上下文从执行上下文栈中弹出
网友评论