在谈及做用域链以前,首先要谈谈做用域bash
概念:在某一区域执行Js代码时,需对变量或函数的值进行访问,而这一区域又提供对变量或函数的查找,并肯定是否能够访问,则称该区域为做用域函数
做用域可分为全局做用域(Global
)与局部做用域(Local
)学习
代码示例:this
<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声明变量,使变量只能在代码块内有效 spa
概念: Js做用域链其实就是从函数内部访问外部函数外部变量的一种机制,它从内到外进行链式查找,那么他是如何进行查找的呢?如下从执行上下文的角度分析prototype
代码示例:3d
<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>
复制代码
因为函数里面再次定义了函数,因此呢,造成一个执行上下文的先后相互引用的关系,也就产生一个做用域链。 code
prototype
其实就是原型,每个函数都有一个原型,它的值是一个对象;Constructor
方法,它指向函数自己_proto_
也是每个对象都具备的属性,它指向建立这个对象的prototype
概念: 若是访问一个对象的属性时,先在这个对象本身的属性中去找,若是找不到,则沿着_proto_
这个属性向中找,若是_proto_
这个对象中仍是没有找到,就在_proto_
对象的_proto_
属性中去找,依次下去,这就是原型链。cdn
代码示例:对象
Function.prototype.new = "New Function !";
function f(){}
console.log(f.new); // New Function !
复制代码
图示以下:
_proto_
找,找不到就往
Function
的
prototype
中找,因为我在
Function
中建立了一个
new
方法,因此能够找到
因为对象的__proto__[隐式原型]与建立这个对象的函数(构造器)的prototype是一致的。 因此理论上,你对__proto__修改会直接影响prototype。
<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>
复制代码