一、作用域链
在谈及作用域链之前,首先要谈谈作用域
1.作用域(Scope)
概念:在某一区域执行Js代码时,需对变量或函数的值进行访问,而这一区域又提供对变量或函数的查找,并确定是否可以访问,则称该区域为作用域
作用域可分为全局作用域(Global)与局部作用域(Local)
代码示例:
<script>
var a = 1; //全局变量
function f(){
var b = 2; //局部变量
console.log(a,b) //1 2
}
f();
console.log(b) //Uncaught ReferenceError: b is not defined
</script>
Js中并没有块级作用域,都是相对函数而言的,而ES6新增可以在函数内用Let声明变量,使变量只能在代码块内有效
2.作用域链(Scope Chain)
概念: Js作用域链其实就是从函数内部访问外部函数外部变量的一种机制,它从内到外进行链式查找,那么他是如何进行查找的呢?以下从执行上下文的角度分析
代码示例:
<script>
var a = 1;
function f(){
var b = 2;
var c = 3;
function f1(){
var d = 4;
function f2(){
console.log(b,c,d); //2,3,4
}
f2();
}
f1();
console.log(b,c); //2,3
console.log(d); //Uncaught ReferenceError: d is not defined
}
f();
</script>
由于函数里面再次定义了函数,所以呢,形成一个执行上下文的前后相互引用的关系,也就产生一个作用域链。
二、原型链(Prototype Chain)
1. 原型(Prototype)
prototype其实就是原型,每一个函数都有一个原型,它的值是一个对象;- 在对象的实例化中包含了很多属性,但其中一定有一个
Constructor方法,它指向函数本身 _proto_也是每一个对象都具有的属性,它指向创建这个对象的prototype
2. 原型链(Prototype Chain)
概念: 如果访问一个对象的属性时,先在这个对象自己的属性中去找,如果找不到,则沿着_proto_这个属性向中找,如果_proto_这个对象中还是没有找到,就在_proto_对象的_proto_属性中去找,依次下去,这就是原型链。
代码示例:
Function.prototype.new = "New Function !";
function f(){}
console.log(f.new); // New Function !
图示如下:
_proto_找,找不到就往Function的prototype中找,由于我在Function中创建了一个new方法,所以可以找到
由于对象的__proto__[隐式原型]与创建这个对象的函数(构造器)的prototype是一致的。 所以理论上,你对__proto__修改会直接影响prototype。
3. 原型扩展:继承
<script>
function Parent(yourname){
this.name = yourname;
}
Parent.prototype.say = function (){
console.log(this.name);
}
function Son(yourname){
Parent.call(this,yourname); //调用父对象的构造器,把当前子类的对象传给this
}
Son.prototype = Parent.prototype; //让子对象的_proto_指向父对象的prototype
Son.prototype.constructor = Son; //让prototype原型上的constructor在指向Son
var s = new Son('Alex');
s.say(); // Alex
</script>