摘要:一直感覺中的是一個大坑,雖然一直都有注意,一直都有研究,但是總是會忘記。即使也沒有權利改變。但是可以影響后面的參數(shù)值。由于只是我根據(jù)經驗和資料自己總結的,所以不知道是否有疏忽或者遺漏,如果有問題的地方,歡迎提出。
一直感覺javascript中的this是一個大坑,雖然一直都有注意,一直都有研究,但是總是會忘記。在這里,總結一下一些簡單的規(guī)律
不考慮箭頭函數(shù)的情況下下面的所有的都是不考慮箭頭函數(shù)的情況下,因為箭頭函數(shù)和普通的差別很大
直接調用的都是window除非是bind綁定過的,其他情況下,直接調用的方法的this都是window。所謂的直接調用,就是直接以method()的形式調用,沒有call, apply, new
看幾種情況:
function foo(){ return this; } foo(); // window
var obj = { foo: function(){ return this; } } var foo = obj.foo; foo(); // window
function Foo(){ this.foo = function(){ console.log(this); } var foo = this.foo; foo(); // window } new Foo();誰調用,誰是this
除非是bind綁定過的,一般情況下,誰調用這個方法,那么內部的this就指向這個對象。也就是說obj.method(),那么就指向obj。obj.foo.method(),那么就指向obj.foo
看幾個例子:
var obj = { foo: function(){ return this; } } obj.foo(); // obj調用,所以結果是obj
function foo(){ return this }; var obj = {}; obj.foo = foo; obj.foo(); // obj調用,所以結果是obj
var obj = { bar: function(){ return this; }, foo: function(){ return this.bar(); } } obj.foo(); // 在foo中, this是obj, 而this調用的bar, 所以返回的是obj
var obj = { bar: { foo: function(){ return this } } } obj.bar.foo(); // obj.bar調用的foo,所以返回的結果是bar
function foo(){ this.bar = function(){ return this } return this.bar(); } foo(); // 由于foo中的this是window, 所以this.bar()返回的是window
function Foo(){ this.foo = function(){ console.log(this); } this.foo(); } var object = new Foo(); // 由于this.foo中的this是object,所以this是objectnew會生成一個新的this
所有情況下,(箭頭函數(shù)不能使用new關鍵字),使用了new以后,會把內部的this指向新生成的對象。
除去bind的情況下,prototype中的this也指向新生成的對象
function Foo(){ console.log(this); // this指向新生成的對象,object } var object = new Foo();
function Foo(){ this.foo = function(){ return this === object; } } var object = new Foo(); object.foo(); // 輸出true
function Foo(){} Foo.prototype.foo = function(){ return this === object; } var object = new Foo(); object.foo(); // 輸出truecall, apply是誰,this就是誰
除非是bind的情況,call, apply是誰,那么內部的this就是誰。
注意:如果是基本類型,那么javascript會把基本類型轉換成Object的形式
也是看例子:
function foo(){ return this; } foo.call("a"); // String typeof foo.call("a"); // object
var obj = { foo : function(){ return this; } } obj.foo.call(1); // Number typeof obj.foo.call(1); // object
function Foo(){ this.foo = function(){ return this; } } var object = new Foo(); object.foo.call(1); // Numberbind是誰,this就是誰
除了new這一種特殊情況,bind的對象是誰,那么this也就是誰。即使call, apply也沒有權利改變。
注意:如果是基本類型,那么javascript會把基本類型轉換成Object的形式
function foo() { return this; } foo = foo.bind(1); foo(); // Number typeof foo(); // object
function foo() { return this; } foo = foo.bind(1); foo.call("a"); // Number 1
function Foo() { return this; } Foo.prototype.foo = (function(){ return this; }).bind(1); var object = new Foo(); object.foo(); // Number
特殊情況
new這個關鍵詞可以改變方法內部的this,使他指向新生成的對象
function Foo(){ this.foo = function(){ console.log(this === obj) } } Foo = Foo.bind(1); var obj = new Foo(); obj.foo(); // 輸入true箭頭函數(shù)
箭頭函數(shù)的"this"是根據(jù)定義環(huán)境的this來定的,也就是說定義的函數(shù)周圍的this是什么,它的"this"就是什么。(注意我在this上加了引號,是因為這個this并不是真的箭頭函數(shù)的this)
而且不會被bind, call, apply所改變
var foo = ()=>{ return this }; foo() // window
var obj = { foo: ()=>this } obj.foo(); // 由于定義的時候,周圍的環(huán)境是window,所以返回window
var obj = { foo(){ var bar= ()=>{ return this }; return bar(); } } obj.foo(); // 由于定義bar的時候,周圍環(huán)境是obj,所以返回obj var foo = obj.foo; foo(); // 同理,這里是window
var foo = ()=>{ return this }; foo = foo.bind(1); foo(); // window foo.call(1); // window foo.apply(1); // window
function Foo(){ // 箭頭函數(shù) var a = ()=>{ console.log(this === object); // true } // 對比普通函數(shù) var b = function(){ console.log(this === window); // true } this.foo = function(){ a(); b(); } } var object = new Foo(); object.foo();
function Foo(){} // window Foo.prototype.foo = ()=>{ return this } // window var object = new Foo(); object.foo(); // 由于定義foo的時候,周圍環(huán)境是window,所以這里是window小結
之前在上面寫的都是記憶方法,方便記憶,但是并沒有涉及到原理,這里大概點幾點:
bind以后,即使再bind, apply, call也不會改變this的值其實可以從bind的簡單實現(xiàn)看出來:
Function.prototype.bind = Function.prototype.bind || function(context, ...args){ var func = this; return function(...currentArgs){ return func.apply(context, args.concat(currentArgs)); } }
所以,從這里看出來,bind以后,返回了一個新的function,所以即使以后再對返回的方法進行bind, apply, call,也只是對新的function操作,并不影響func.apply(context...)中的context值。但是可以影響后面的參數(shù)值。
關于bind方法的介紹,今天看到顏海鏡、顏大的文檔,感覺對bind的了解加深一步,附上鏈接
關于箭頭函數(shù)的this根據(jù)MDN的文檔,箭頭函數(shù)是不會生成自己的this的(還有arguments)。所以我才給上面的this加上雙引號。而且由于它本身并沒有this,所以才不會被apply,bind, call所改變。
那么在箭頭函數(shù)中調用的this是怎么來定的呢?
下面來自vajoy的一篇譯文
雖然箭頭函數(shù)沒有一個自己的this,但當你在內部使用了this的時候,他會指向最近一層作用域的this
function foo(){ return ()=>{ return ()=>{ return ()=>{ console.log("id:", this.id); } } } } foo.call({id:42})()()(); // id:42
這里只有一次this的綁定,也就是foo()的時候.
這些連接內嵌的函數(shù)們都沒有生命他們自己的this,所以this.id的引用會簡單地順著作用域鏈查找,一直查找到foo()函數(shù),他是第一處能找到一個確切存在的this的地方。
由于只是我根據(jù)經驗和資料自己總結的,所以不知道是否有疏忽或者遺漏,如果有問題的地方,歡迎提出。謝謝
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/81542.html
摘要:專題系列第十七篇,講解函數(shù)記憶與菲波那切數(shù)列的實現(xiàn)定義函數(shù)記憶是指將上次的計算結果緩存起來,當下次調用時,如果遇到相同的參數(shù),就直接返回緩存中的數(shù)據(jù)。 JavaScript 專題系列第十七篇,講解函數(shù)記憶與菲波那切數(shù)列的實現(xiàn) 定義 函數(shù)記憶是指將上次的計算結果緩存起來,當下次調用時,如果遇到相同的參數(shù),就直接返回緩存中的數(shù)據(jù)。 舉個例子: function add(a, b) { ...
摘要:賦予了函數(shù)非常多的特性,其中最重要的特性之一就是將函數(shù)作為第一型的對象。那就意味著在中函數(shù)可以有屬性,可以有方法,可以享有所有對象所擁有的特性。參考資料忍者秘籍關于函數(shù)我之前還寫過一篇中高階函數(shù)的魅力有興趣的話可以看一看。 Javascript賦予了函數(shù)非常多的特性,其中最重要的特性之一就是將函數(shù)作為第一型的對象。那就意味著在javascript中函數(shù)可以有屬性,可以有方法, 可以享有...
摘要:不同于其它靜態(tài)編程語言,實現(xiàn)組合模式的難點是保持樹對象與葉對象之間接口保持統(tǒng)一,可借助定制接口規(guī)范,實現(xiàn)類型約束。誤區(qū)規(guī)避組合不是繼承,樹葉對象并不是父子對象組合模式的樹型結構是一種聚合的關系,而不是。 showImg(https://segmentfault.com/img/bVbu79V?w=800&h=600); 組合模式:又叫 部分整體 模式,將對象組合成樹形結構,以表示 部分...
摘要:來源編程精解中文第三版翻譯項目原文譯者飛龍協(xié)議自豪地采用谷歌翻譯置疑計算機能不能思考就相當于置疑潛艇能不能游泳。這張圖將成為我們的機器人在其中移動的世界。機器人在收到包裹時拾取包裹,并在抵達目的地時將其送達。這個機器人已經快了很多。 來源:ApacheCN『JavaScript 編程精解 中文第三版』翻譯項目原文:Project: A Robot 譯者:飛龍 協(xié)議:CC BY-NC-S...
摘要:我們需要知道的是,對于而言,匿名函數(shù)是一個很重要且具有邏輯性的特性。通常,匿名函數(shù)的使用情況是創(chuàng)建一個供以后使用的函數(shù)。截圖自忍者秘籍通過完善之前對匿名函數(shù)的粗略定義,我們可以修復解決這個問題。 從名字即可看書,此篇博客總結與《JavaScript忍者秘籍》。對于JavaScript來說,函數(shù)為第一類型對象。所以這里,我們主要是介紹JavaScript中函數(shù)的運用。 系列博客地址:h...
閱讀 3316·2023-04-25 19:42
閱讀 1334·2021-11-23 10:11
閱讀 2272·2021-11-16 11:51
閱讀 1596·2019-08-30 15:54
閱讀 2040·2019-08-29 18:44
閱讀 1619·2019-08-23 18:24
閱讀 496·2019-08-23 17:52
閱讀 1770·2019-08-23 15:33