XFE 技术 生活 笔记 文集

javascript核心基础总结

🔖 javascript 👀 116 🕒 2018-03-05 👨‍🎓 戡玉

对《深入理解javascript原型和闭包系列》,《深入理解javascript系列》和《javascript深入系列》的学习总结

词法作用域

  1. 作用域就是,程序查找变量和有效执行所在的区域,也称词法作用域。
  2. 词法作用域分为,静态作用域和动态作用域。
  3. 静态作用域取决于程序代码定义的时候,动态作用域取决于程序动态执行时的具体作用域环境。
  4. js采用静态作用域,对于变量对象的获取只基于定义环境,而不受执行变化的影响。
  5. 实例如下:
    var scope = "global scope";
    function checkscope(){
     var scope = "local scope";
     function f(){
         return scope;
     }
     return f;
    }
    checkscope()(); //结果为local scope

执行上下文栈

  1. js可执行代码类型分为3种:全局代码、函数代码、eval代码。
  2. 执行时,会进行代码分析,以一种执行栈的方式去执行代码,类似数组的入栈和出栈,以后进先出的方式完成代码执行
  3. 压栈和出栈的内容,被称之为执行上下文,又分为全局上下文和函数上下文。
  4. 压栈的时候,js引擎首先遇到的即是全局代码,也就是全局上下文,然后就是可执行的函数上下文。

执行上下文

  1. 全局代码和函数代码在被引擎分析时,都会形成一个入栈对象,称之为执行上下文。
  2. 可以将其抽象的理解为object,用来追踪关联代码的执行进度。
  3. 包含3个属性:变量对象,作用域链,this。
  4. 拥有2个状态:代码准备,代码执行。

变量对象

  1. 变量对象就是,与执行上下文相关的数据作用域,包含变量,形参和函数声明等。
  2. 因为存在全局上下文和函数上下文之分,所以在变量对象上存在区别。
  3. 在全局上下文中,变量对象就是宿主环境代表的window,初始化拥有规范内置的一系列属性,在进入全局上下文时,会给window添加变量和函数声明等初始值。
  4. 在函数上下文中,变量对象初始化时只拥arguments属性对应的Arguments对象,在进入函数上下文时,会给变量对象添加形参、函数声明、变量声明等初始值。
  5. 在代码准备阶段(进入上下文时),会给变量对象的属性赋入初始值;在代码执行阶段,会再次修改变量对象的属性值。
  6. 在全局上下文中,变量对象属性就称为VO(变量对象);在函数上下文中,变量对象属性就被称为AO(活动对象)

作用域链

  1. 当查找变量时,js会先从当前上下文的变量对象中查找,如果没有找到,就会从父级上下文的变量对象中查找,这样由多个执行上下文的变量对象构成的链表就叫做作用域链。
  2. 在js中,全局上下文属于一级链条,函数上下文开始为次级链条。
  3. 函数有一个作用域属性[[scope]],用于保存父变量对象,作为父变量对象的层级链存在,一级一级直至全局上下文的变量对象,因而构成作用域链。
  4. 函数创建时,函数的作用域属性[[scope]]也被创建,直至函数销毁前一直存在。
  5. 函数激活时(进入函数上下文时),创建AO(活动对象)后就会将其添加到作用链的前端,因此变量查找才会一级一级逐上。
  6. 通过Function函构造函数创建的函数的[[scope]]属性总是唯一的全局对象。

this

  1. 在一个上下文中,this由调用者提供,由调用的方式决定,因此this为何值只取决于调用时。
  2. 调用函数方式对this值的影响取决于规范里的抽象类型Reference(包含base value,referenced name和strict reference)。
  3. 在函数调用中,如果调用括号()的左边是引用类型(Reference type)的值,this将设为引用类型值的base对象(base object),在其他情况下(与引用类型不同的任何其它属性),这个值为null(第5版的ECMAScript中,已经不强迫转换成全局变量了,而是赋值为undefined)。
  4. 在分析this的时,这里的引用类型是指代的是程序内部运行的描述名称,具体可参考ECMAScript 5.1,或者这篇文章
  5. 实例如下:
var value = 1;
var foo = {
  value: 2,
  bar: function () {
      return this.value;
  }
}

//示例1
console.log(foo.bar()); //2
//示例2
console.log((foo.bar)()); //2
//示例3
console.log((foo.bar = foo.bar)()); //1
//示例4
console.log((false || foo.bar)()); //1
//示例5
console.log((foo.bar, foo.bar)()); //1

闭包

  1. 在自身的作用域外被调用并使得作用域和活动对象被保存的现象,也就是内部作用域被外部作用域持有的情况。
  2. 从理论角度讲,所有的JavaScript函数都是闭包,因为它们都在创建的时候就将上层上下文的数据保存起来了。
  3. 从实践角度讲,一个函数执行时将内部函数引用返回给外部变量持有时就产生了闭包,返回的内部函数依然会持有执行函数的上下文。

原型与原型链

  1. 每一个函数都拥有一个prototype属性,每一个js对象都拥有一个proto属性
  2. prototype和proto的关系是,prototype属于对应js对象的proto所指
  3. 所有js函数(包括内置函数)的prototype都指向Object.prototype,所有函数作为对象,其proto都指向Function内置对象的prototype
  4. js内置函数中,只有Function内置函数的proto指向了自身的prototype,被自身创建
  5. js内置函数中,只有Object的prototype的proto为null,属于原型链的终点
  6. 每个prototype都有一个constructor属性指向关联的构造函数,每一个通过new进行初始化的函数实例的proto都指向函数的prototype
  7. js通过prototype和proto的关系实现了一个委托链条,proto一级接一级构成原型链

参数传递

输入图片说明

实例代码如下

var obj = {
    value: 1
};
function foo(o) {
    o = 2;
    console.log(o); //2
}
foo(obj);
console.log(obj.value) // 1

说明图如下

输入图片说明