摘要:避免從構造函數返回任何東西,因為它可能會替換所產生的實例。避免使用使用也能創建一個實例然而這不會調用構造函數。因為不會調用構造函數,所以這是一個有效的創建繼承模式的方法,能夠重寫原型鏈上的構造函數。
一. 全局 this
1.在瀏覽器中,在一個全局環境中,this就是window對象。
2.在瀏覽器中,在全局中使用var相當于分配給this或者window
3.假如你創建一個新的變量,不使用var或者let(ECMAScript6),你是添加或者改變全局this的屬性
4.在node中使用repl,this是最頂級的命名空間,你可以認為是global
> this { ArrayBuffer: [Function: ArrayBuffer], Int8Array: { [Function: Int8Array] BYTES_PER_ELEMENT: 1 }, Uint8Array: { [Function: Uint8Array] BYTES_PER_ELEMENT: 1 }, ... > global === this true
5.在node中執行腳本,在全局中this是一個空對象,而不與global相等
test.js: console.log(this); console.log(this === global);
$ node test.js {} false
6.在node中,全局環境中的var并非像在瀏覽器中執行腳本一樣,分配給this。
test.js: var foo = "bar"; console.log(this.foo);
$ node test.js undefined
但是在repl中是一樣的
> var foo = "bar"; > this.foo bar > global.foo bar
7.在node中,使用腳本執行,不用var或者let創建的變量會添加到global而不是this.
test.js foo = "bar"; console.log(this.foo); console.log(global.foo);
$ node test.js undefined bar
在repl中,它是分配到這兩個上的。
二. 函數中的this除了DOM事件處理程序或者一個thisArg已經設置的情況外,在node和瀏覽器中,函數中(不實例化new)的this是全局范圍的。
test.js: foo = "bar"; function testThis () { this.foo = "foo"; } console.log(global.foo); testThis(); console.log(global.foo);
$ node test.js bar foo
除非你使用user strict,this會變為underfined
當你new一個函數的時候,this會成為一個新的上下文,不等同于全局this
三. 原型中的this函數對象有一個特殊的屬性prototype,當你創建一個函數實例,可以訪問prototype屬性,可以使用this進行訪問
function Thing() { console.log(this.foo); } Thing.prototype.foo = "bar"; var thing = new Thing(); //logs "bar" console.log(thing.foo); //logs "bar"
加入創建多個實例化,它們共享原型上的值,this.foo都會返回相同的值,除非你在實例化函數上進行覆蓋。
function Thing() { } Thing.prototype.foo = "bar"; Thing.prototype.logFoo = function () { console.log(this.foo); } Thing.prototype.setFoo = function (newFoo) { this.foo = newFoo; } var thing1 = new Thing(); var thing2 = new Thing(); thing1.logFoo(); //logs "bar" thing2.logFoo(); //logs "bar" thing1.setFoo("foo"); thing1.logFoo(); //logs "foo"; thing2.logFoo(); //logs "bar"; thing2.foo = "foobar"; thing1.logFoo(); //logs "foo"; thing2.logFoo(); //logs "foobar";
this在一個實例中是一個特殊的對象,this實際是一個關鍵字,可以認為this作為一種方法去訪問prototype,直接分配給this,將會覆蓋原來prototype上的方法。你可以刪除this掛接的方法,從而恢復訪問默認prototype
function Thing() { } Thing.prototype.foo = "bar"; Thing.prototype.logFoo = function () { console.log(this.foo); } Thing.prototype.setFoo = function (newFoo) { this.foo = newFoo; } Thing.prototype.deleteFoo = function () { delete this.foo; } var thing = new Thing(); thing.setFoo("foo"); thing.logFoo(); //logs "foo"; thing.deleteFoo(); thing.logFoo(); //logs "bar"; thing.foo = "foobar"; thing.logFoo(); //logs "foobar"; delete thing.foo; thing.logFoo(); //logs "bar";
或者直接引用函數對象的原型。
function Thing() { } Thing.prototype.foo = "bar"; Thing.prototype.logFoo = function () { console.log(this.foo, Thing.prototype.foo); } var thing = new Thing(); thing.foo = "foo"; thing.logFoo(); //logs "foo bar";
創建的實例都共享相同的屬性和方法,如果給prototype分配一個數組,所有實例都能夠訪問。
function Thing() { } Thing.prototype.things = []; var thing1 = new Thing(); var thing2 = new Thing(); thing1.things.push("foo"); console.log(thing2.things); //logs ["foo"]
在prototype上分配一個數組通常是一個錯誤,如果希望每個實例都有自己的數組,那在函數中創建。
function Thing() { this.things = []; } var thing1 = new Thing(); var thing2 = new Thing(); thing1.things.push("foo"); console.log(thing1.things); //logs ["foo"] console.log(thing2.things); //logs []
this可以通過原型鏈找到相應的方法。
function Thing1() { } Thing1.prototype.foo = "bar"; function Thing2() { } Thing2.prototype = new Thing1(); var thing = new Thing2(); console.log(thing.foo); //logs "bar"
在javascript中可以使用原型鏈模擬傳統面向對象繼承。
使用函數內含有綁定this的方法或者屬性去創建原型鏈,將會隱藏上層原型鏈定義的內容。
function Thing1() { } Thing1.prototype.foo = "bar"; function Thing2() { this.foo = "foo"; } Thing2.prototype = new Thing1(); function Thing3() { } Thing3.prototype = new Thing2(); var thing = new Thing3(); console.log(thing.foo); //logs "foo"
我喜歡叫綁定在原型上的函數為methods.在methods中使用this綁定某個值,將會覆蓋原型上的相關定義。
function Thing1() { } Thing1.prototype.foo = "bar"; Thing1.prototype.logFoo = function () { console.log(this.foo); } function Thing2() { this.foo = "foo"; } Thing2.prototype = new Thing1(); var thing = new Thing2(); thing.logFoo(); //logs "foo";
在JavaScript嵌套函數中,雖然可以捕獲到父函數中的變量,但是不繼承this
function Thing() { } Thing.prototype.foo = "bar"; Thing.prototype.logFoo = function () { var info = "attempting to log this.foo:"; function doIt() { console.log(info, this.foo); } doIt(); } var thing = new Thing(); thing.logFoo(); //logs "attempting to log this.foo: undefined"
函數doIt中的this指向global,在use strict下則為undefined,這是很多不熟悉this用法的人痛苦的根源之一。
更壞的情況是,將一個實例方法作為參數傳入函數。this將指向global,在use strict下則為undefined。
function Thing() { } Thing.prototype.foo = "bar"; Thing.prototype.logFoo = function () { console.log(this.foo); } function doIt(method) { method(); } var thing = new Thing(); thing.logFoo(); //logs "bar" doIt(thing.logFoo); //logs undefined
一些人把this賦值給一個變量,通常叫self,能夠避免this指向global這個問題。
function Thing() { } Thing.prototype.foo = "bar"; Thing.prototype.logFoo = function () { var self = this; var info = "attempting to log this.foo:"; function doIt() { console.log(info, self.foo); } doIt(); } var thing = new Thing(); thing.logFoo(); //logs "attempting to log this.foo: bar"
但是這種方法在將一個實例方法作為參數傳入函數情況下,不起作用
function Thing() { } Thing.prototype.foo = "bar"; Thing.prototype.logFoo = function () { var self = this; function doIt() { console.log(self.foo); } doIt(); } function doItIndirectly(method) { method(); } var thing = new Thing(); thing.logFoo(); //logs "bar" doItIndirectly(thing.logFoo); //logs undefined
解決這個方法,可以使用函數綁定的方法bind。
function Thing() { } Thing.prototype.foo = "bar"; Thing.prototype.logFoo = function () { console.log(this.foo); } function doIt(method) { method(); } var thing = new Thing(); doIt(thing.logFoo.bind(thing)); //logs bar
你也可以使用apply或者call在新的上下文環境中調用方法或者函數。
function Thing() { } Thing.prototype.foo = "bar"; Thing.prototype.logFoo = function () { function doIt() { console.log(this.foo); } doIt.apply(this); } function doItIndirectly(method) { method(); } var thing = new Thing(); doItIndirectly(thing.logFoo.bind(thing)); //logs bar
可以使用bind替換this,適用于任何函數或方法,即使沒有在實例原型上定義。
function Thing() { } Thing.prototype.foo = "bar"; function logFoo(aStr) { console.log(aStr, this.foo); } var thing = new Thing(); logFoo.bind(thing)("using bind"); //logs "using bind bar" logFoo.apply(thing, ["using apply"]); //logs "using apply bar" logFoo.call(thing, "using call"); //logs "using call bar" logFoo("using nothing"); //logs "using nothing undefined"
避免從構造函數返回任何東西,因為它可能會替換所產生的實例。
function Thing() { return {}; } Thing.prototype.foo = "bar"; Thing.prototype.logFoo = function () { console.log(this.foo); } var thing = new Thing(); thing.logFoo(); //Uncaught TypeError: undefined is not a function
奇怪的是,假如你返回的是原始值(string或者number),返回語句將會被忽略。最好不要從你打算調用的構造函數中返回任何東西,即使你知道你在做什么。如果你想創建一個工廠模式,使用一個函數來創建實例,不要用new的。當然,這只是個人觀點。
避免使用new`,使用Object.create也能創建一個實例
function Thing() { } Thing.prototype.foo = "bar"; Thing.prototype.logFoo = function () { console.log(this.foo); } var thing = Object.create(Thing.prototype); thing.logFoo(); //logs "bar"
然而這不會調用構造函數。
function Thing() { this.foo = "foo"; } Thing.prototype.foo = "bar"; Thing.prototype.logFoo = function () { console.log(this.foo); } var thing = Object.create(Thing.prototype); thing.logFoo(); //logs "bar"
因為Object.create不會調用構造函數,所以這是一個有效的創建繼承模式的方法,能夠重寫原型鏈上的構造函數。
function Thing1() { this.foo = "foo"; } Thing1.prototype.foo = "bar"; function Thing2() { this.logFoo(); //logs "bar" Thing1.apply(this); this.logFoo(); //logs "foo" } Thing2.prototype = Object.create(Thing1.prototype); Thing2.prototype.logFoo = function () { console.log(this.foo); } var thing = new Thing2();四. 對象中的this
可以在對象的任何函數中使用this來引用該對象上的其他屬性。這與使用new實例不同。
var obj = { foo: "bar", logFoo: function () { console.log(this.foo); } }; obj.logFoo(); //logs "bar"
不使用new,Object.create ,function 去創建一個對象,也可以像實例化一樣綁定到對象上。
var obj = { foo: "bar" }; function logFoo() { console.log(this.foo); } logFoo.apply(obj); //logs "bar"
當你像下面使用this時,沒有順著對象的層次結構。只有直接父對象上的屬性才能通過this進行訪問
var obj = { foo: "bar", deeper: { logFoo: function () { console.log(this.foo); } } }; obj.deeper.logFoo(); //logs undefined
你可以直接使用你想要的屬性。
var obj = { foo: "bar", deeper: { logFoo: function () { console.log(obj.foo); } } }; obj.deeper.logFoo(); //logs "bar"五. DOM event中的this
在一個HTML DOM event處理程序中,this通常是指DOM element event綁定的對象
function Listener() { document.getElementById("foo").addEventListener("click", this.handleClick); } Listener.prototype.handleClick = function (event) { console.log(this); //logs "" } var listener = new Listener(); document.getElementById("foo").click();
除非你綁定新的上下文
function Listener() { document.getElementById("foo").addEventListener("click", this.handleClick.bind(this)); } Listener.prototype.handleClick = function (event) { console.log(this); //logs Listener {handleClick: function} } var listener = new Listener(); document.getElementById("foo").click();六. HTML中的this
在HTML屬性中可以放js代碼,this指向當前的元素
this的覆蓋
你不能夠復寫this,因為它是一個關鍵詞
function test () { var this = {}; // Uncaught SyntaxError: Unexpected token this }七. eavl中的this
可以使用eavl訪問this
function Thing () { } Thing.prototype.foo = "bar"; Thing.prototype.logFoo = function () { eval("console.log(this.foo)"); //logs "bar" } var thing = new Thing(); thing.logFoo();
這種做法有安全隱患,可以使用Function訪問this
function Thing () { } Thing.prototype.foo = "bar"; Thing.prototype.logFoo = new Function("console.log(this.foo);"); var thing = new Thing(); thing.logFoo(); //logs "bar"八. with中的this
可以使用with將this添加到當前的范圍來讀取和寫入值,而不用顯式調用。
function Thing () { } Thing.prototype.foo = "bar"; Thing.prototype.logFoo = function () { with (this) { console.log(foo); foo = "foo"; } } var thing = new Thing(); thing.logFoo(); // logs "bar" console.log(thing.foo); // logs "foo"
很多人認為這是錯的做法,鑒于with引起的歧義。
九. jQuery中的this像HTML DOM elements的事件處理程序一樣,jQuery在很多地方使用this指向DOM元素。比如$.each
鑒于筆者翻譯水平有限,有什么問題歡迎提出指教。
十.參考資料原文地址:all this
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/80248.html
摘要:事件驅動正是一種回調函數設計模式。由于不支持多線程,所以為了實現并行處理,不得不使用回調函數,這逐漸成為了一種慣例。上面的回調函數只是單純的函數而不具有狀態。如果回調函數具有狀態,就能得到更為廣泛的應用。 回調函數模式 回調函數與控制反轉 回調函數是程序設計的一種方法。這種方法是指,在傳遞了可能會進行調用的函數或對象之后,在需要時再分別對其進行調用。由于調用方與被調用方的依賴關系與通常...
摘要:此時使用設置當前值中的猜測值為輸入框的內容值。接著判斷猜測之是否大于或者小于,因為這兩者是范圍之外不再進行判斷,所以最開始使用進行判斷不能小于不能大于以上代碼中表示調用微信小程序接口彈出提示,傳入的參數為提示內容。 ...
摘要:怎么樣好不好最近美國新的全解鎖原生段上架開售,支持等,原一期產品可加價更換年付免費更換,美國原生段仍有少量剩余,套餐原價基礎上每月加價元可更換美國原生,更換的為純凈新分配美國段,絕對傳家寶產品,支持解鎖美區游戲,,等,同時支持。lisahost怎么樣?lisahost好不好?lisahost最近美國新的全解鎖原生IP 206段上架開售,支持tiktok等,原CN2一期產品可加價更換(年付免費...
閱讀 3384·2023-04-25 20:37
閱讀 3142·2021-09-07 09:59
閱讀 1665·2019-08-29 12:43
閱讀 1185·2019-08-28 18:27
閱讀 479·2019-08-26 13:50
閱讀 2025·2019-08-26 10:33
閱讀 3591·2019-08-23 18:39
閱讀 2390·2019-08-23 18:09