在談及做用域鏈以前,首先要談談做用域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 !
複製代碼
圖示以下:
函數f調用new方法,先從本身的_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>
複製代碼