一、this.xx 和 xx 是兩回事 受後端語言影響,總把this.xx 和xx 當中一回事,認為在function中,xx 就是this.xx,其實完全兩回事; this.xx 是沿著this 原型鏈找變數,xx是沿著作用域鏈找變數 var func = function(){ console. ...
一、this.xx 和 xx 是兩回事
受後端語言影響,總把this.xx 和xx 當中一回事,認為在function中,xx 就是this.xx,其實完全兩回事;
this.xx 是沿著this 原型鏈找變數,xx是沿著作用域鏈找變數
var func = function(){ console.info(this); } var func1 = function(){ function func11(){ console.info(this) // 應該是func1 this.func(); // this 是window func(); // windows 輸出 } console.info(this) func11(); // 全局調用,func11 裡面的this是全局對象window, 見下麵的2 //this.func11(); //失敗,this是window,沒有func11方法 } func1()View Code
元原型鏈:this.xxx 的時候會沿著原型鏈查找,繼承可以通過原型鏈實現
作用域鏈:xxx 的時候會沿著作用域鏈查找,with 會設置作用域鏈最底層
二、this代表啥
this對象根據不同的調用方式,所綁定的對象也是不同的。
函數調用有四種:
1. 方法模式的調用:當一個函數被保存為一個對象的屬性時,我們稱這個函數為一個方法。當一個方法被調用時,this綁定到該對象。
var p = {func: func1} p.func()// func1中的this就p
2. 函數模式的調用:當一個函數並非一個對象的屬性時,那麼它就被當作一個函數來調用,this被綁定到全局對象。
3. 構造器模式的調用:如果一個函數前面帶上new來調用,那麼將創建一個隱藏連接到該函數的prototype成員的新對象,同時this被綁定到這個新對象上。
function person(){ console.info(this); this.age = 10; } var a = new person()
4. apply模式的調用:apply方法接收兩個參數,第一個被綁定到this,第二個是參數數組。什麼也不傳時,預設this綁定到全局對象。
var person = function(){ this.age = 10; this.say = function(){console.info(this.age)} } var zl = function(){ person.call(this) console.info(this) } var a = new zl()
// 下麵這個其實是錯誤的繼承,涉及到變數提升,
var person; var zl; person = function(){ this.age = 10; this.say = function(){ console.info(this.age) } } zl = function(){ console.info(zl);//其實是給zl 加了屬性、方法 person.call(zl); } // 執行 var a = new zl() // 執行時候,zl, person 都已經定義出來了,在執行zl() 的時候,會沿著作用域鏈找到zl
三、變數提升
----------------- say() console.info(a); function say(){ console.info(111) } var a = 100; -----------js解析後為,然後其實是執行下麵的代碼--------- function say(){ console.info(111) } var a; say() console.info(a) a = 100;
四、一個奇怪的事情,with,變數提升,this
({ x: 10, foo: function () { function bar() { console.log(x); console.log(y); console.log(this.x); } with (this) { var x = 20; var y = 30; bar.call(this); } } }).foo();
----js引擎解析翻譯後----
({ x: 10, foo: function () { var x; var y; function bar() { console.log(x); // 沿著作用域找到了foo 下麵的x=undefined console.log(y); // 沿著作用域鏈找到 foo 下麵的 y=30 console.log(this.x);// this 是最外面的對象,x 已經改為20 } with (this) { x = 20; //this是最外面的對象,有x,其實是賦值給了this.x, 10變成20 y = 30; // this 沒有y,沿著作用域鏈找到 foo 下麵的y, undefine 變成30 bar.call(this); } } }).foo();
輸出:
undefine
30
20
題目來自 http://luopq.com/2016/02/14/js-with-keyword/
http://luopq.com/2016/02/14/js-with-keyword/