Js中的链(作用域链、原型链)


Js中存在两种老生常谈的链,作用域链和原型链。作用域链是为了访问变量而存在的链,原型链是访问对象的属性而存在的链。


作用域链

说到作用域链,首先来说下作用域的概念:执行代码的上下文,也可以说是变量对象,是开始进入一个函数的执行环境的时候,形成的所有可访问变量,可以说变量对象是作用域的实体。

作用域分类:全局作用域、函数作用域(块级作用域)、eval作用域。ES6之前的块级作用域只指函数作用域,ES6以后,if,while,switch,for语句都可以形成自己的块级作用域(使用非var来声明变量)。全局作用域是作用域链的最顶层。

作用域链的概念:是由作用域组成的一个带头结点的单向链表,主要作用域是用来查找变量的。【scope】属性是一个指向这个链表头结点的指针。具体来说形成过程:在定义一个函数的时候,在函数内部会会创建一个scope属性,这个属性指向一个作用域链。在确定其scope属性的时候,js解析器按照一定的规则来确认作用域链:从函数内部向外遍历,每当遇到一个function的时候,就把这个function的变量对象添加到作用域链上,一直到最顶层wind我对象。最后再把作用域链的引用赋给scope属性。


原型链

说到原型链,首先说下原型,原型就是原型对象,普通对象(不是通过new Function创建的对象)没有原型对象,只有函数对象才有原型对象。

上图的关系为

Dog.prototype.constructor = Dog

doggie.constructor = Dog

好像doggie和Dog.prototype有点联系,其实也就反映了Dog.prototype是Dog的一个实例,是一个普通的对象不是函数对象。但是有个例外是Function.prototype是个函数对象,理由如下:

var A = new  Person();   Person.prototype = A;//普通对象

var A = new  Function();  Function.prototype = A;//函数对象

原型链是通过__proto__属性形成的,任何对象(普通对象和函数对象)都有__proto__属性。查找对象的某个属性的时候,首先在当前对象查找,如果没有去对象的__proto__中去查找,一直到最顶层null,这样形成的一条查找链就是原型链。

所有对象的 __proto__都指向他的构造函数的prototype

所有函数对象(Number,String,Date,Object等12种内置构造函数,还包括自定义构造函数)的 __proto__都指向Function.prototype(他是一个空函数empty function)

所有的构造函数的prototype类型如下:

你可能感兴趣的:(Js中的链(作用域链、原型链))