-
Notifications
You must be signed in to change notification settings - Fork 4
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
JavaScript深入尝试 #23
Comments
原型和原型链function Person () {}
var person = new Person() person.__proto__ === Person.prototype
Object.getPrototypeOf(person) === Person.prototype Person === Person.prototype.constructor Person.prototype.__proto__ === Object.prototype
Object.getPrototypeOf(Person.prototype) === Object.prototype Object.prototype.__proto__ === null |
作用域JavaScript 采用词法作用域(也就是静态作用域),意味着作用域是由书写代码时函数声明的位置来决定的。 来看个栗子: 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()(); 上面两端代码执行结果都是 JavaScript 函数的执行用到了作用域链,这个作用域链是在函数定义的时候创建的。嵌套的函数 f() 定义在这个作用域链里,其中的变量 scope 一定是局部变量,不管何时何地执行函数 f(),这种绑定在执行 f() 时依然有效。 |
上面两段代码执行的结果一样,但是两段代码究竟有哪些不同呢? 答案就是执行上下文栈的变化不一样。 让我们模拟第一段代码:
让我们模拟第二段代码:
|
执行上下文当 JavaScript 执行一段可执行代码时,会创建对应的执行上下文(执行环境),执行上下文可以抽象的理解为一个 object,由以下几个属性构成:
|
变量对象 VO每一个执行上下文都会分配一个 变量对象(variable object) ,变量对象的属性由 变量(variable) 和 函数声明(function declaration) 构成,变量对象保存了当前作用域的所有函数和变量。 活动对象 AO在函数上下文中,我们用活动对象(activation object, AO)来表示变量对象。 当函数被激活,那么一个活动对象就会被创建并且分配给执行上下文。活动对象由特殊对象 arguments 初始化而成。随后,他被当做变量对象用于变量初始化。 变量对象的创建过程
function a(name, age){
var gender = "male";
function b(){}
}
a(“k”,10);
|
作用域链当查找变量的时候,会先从当前上下文的变量对象中查找,如果没有找到,就会从父级(词法层面上的父级)执行上下文的变量对象中查找,一直找到全局上下文的变量对象,也就是全局对象。这样由多个执行上下文的变量对象构成的链表就叫做作用域链。 以下面的例子为例,结合着之前讲的变量对象和执行上下文栈,我们来总结一下函数执行上下文中作用域链和变量对象的创建过程: var scope = "global scope";
function checkscope(){
var scope2 = 'local scope';
return scope2;
}
checkscope(); 执行过程如下: 1.checkscope 函数被创建,保存作用域链到 内部属性[[scope]] checkscope.[[scope]] = [
globalContext.VO
]; 2.执行 checkscope 函数,创建 checkscope 函数执行上下文,checkscope 函数执行上下文被压入执行上下文栈 ECStack = [
checkscopeContext,
globalContext
]; 3.checkscope 函数并不立刻执行,开始做准备工作,第一步:复制函数[[scope]]属性创建作用域链 checkscopeContext = {
Scope: checkscope.[[scope]],
} 4.第二步:用 arguments 创建活动对象,随后初始化活动对象,加入形参、函数声明、变量声明
5.第三步:将活动对象压入 checkscope 作用域链顶端 checkscopeContext = {
AO: {
arguments: {
length: 0
},
scope2: undefined
},
Scope: [AO, [[Scope]]]
} 6.准备工作做完,开始执行函数,随着函数的执行,修改 AO 的属性值 checkscopeContext = {
AO: {
arguments: {
length: 0
},
scope2: 'local scope'
},
Scope: [AO, [[Scope]]]
} 7.查找到 scope2 的值,返回后函数执行完毕,函数上下文从执行上下文栈中弹出 ECStack = [
globalContext
]; |
原型链,继承,作用域,上下文,this,闭包,传参,call,apply,bind,new。。
主要参考:mqyqingfeng/Blog#17 和 《你不知道的JavaScript》
The text was updated successfully, but these errors were encountered: