JavaScript中所有对象都是Object的实例,并且都继承Object.prototype的属性和方法。也就是说,所有的对象都有prototype属性。
①__proto__和constructor属性是对象所独有的;
② prototype属性是函数所独有的。但是由于JS中函数也是一种对象,所以函数也拥有__proto__和constructor属性,这点是致使我们产生困惑的很大原因之一。
每个构造函数都有一个prototype属性,指向它的原型对象,而且构造函数生成的每个实例也都有一个指向原型对象的内部指针。原型对象上的属性和方法是它所属构造函数生成的实例共享的。
原型链
访问一个实例属性时, 首先会在当前实例中搜索该属性,如果没找到,则会继续搜索实例的原型对象,如果我们将原型对象等于其他构造函数生成的实例,则原型对象将包含一个指向另一个原型的指针,相应地,另一个原型也可以指向其他实例,这样就构成了实例与原型的之间的链条,这就是原型链。
查找会沿着原型链向上,直达找到这个属性或者到达原型链末端才会停下来,这是比较消耗内存的,所以我们不能将原型链定义得太长。
执行上下文
当调用一个函数时,就会为该函数创建一个执行上下文,可以理解为“代码的执行环境”,一个执行上下文的生命周期可以分为两个阶段:
1.创建阶段
在这个阶段中,执行上下文会分别创建变量对象,建立作用域链,以及确定this的指向。
2.代码执行阶段
创建完成之后,就会开始执行代码,这个时候,会完成变量赋值,函数引用,以及执行其他代码。
作用域
作用域是js引擎根据名称查找变量的一套规则。
当存在多个作用域嵌套时,就形成了作用域链。作用域链是在执行上下文的创建阶段确定的,它只与函数声明位置有关。
无论函数在哪里被调用,也无论它如何被调用,它的词法作用域都只由函数被声明时所处的位置决定。 ——《你不知道的JavaScript 上卷》P16
如果js引擎在当前作用域中查找不到某个变量,就会到外层作用域查找。