摘要:避免從構(gòu)造函數(shù)返回任何東西,因?yàn)樗赡軙?huì)替換所產(chǎn)生的實(shí)例。避免使用使用也能創(chuàng)建一個(gè)實(shí)例然而這不會(huì)調(diào)用構(gòu)造函數(shù)。因?yàn)椴粫?huì)調(diào)用構(gòu)造函數(shù),所以這是一個(gè)有效的創(chuàng)建繼承模式的方法,能夠重寫(xiě)原型鏈上的構(gòu)造函數(shù)。
一. 全局 this
1.在瀏覽器中,在一個(gè)全局環(huán)境中,this就是window對(duì)象。
2.在瀏覽器中,在全局中使用var相當(dāng)于分配給this或者window
3.假如你創(chuàng)建一個(gè)新的變量,不使用var或者let(ECMAScript6),你是添加或者改變?nèi)?b>this的屬性
4.在node中使用repl,this是最頂級(jí)的命名空間,你可以認(rèn)為是global
> this { ArrayBuffer: [Function: ArrayBuffer], Int8Array: { [Function: Int8Array] BYTES_PER_ELEMENT: 1 }, Uint8Array: { [Function: Uint8Array] BYTES_PER_ELEMENT: 1 }, ... > global === this true
5.在node中執(zhí)行腳本,在全局中this是一個(gè)空對(duì)象,而不與global相等
test.js: console.log(this); console.log(this === global);
$ node test.js {} false
6.在node中,全局環(huán)境中的var并非像在瀏覽器中執(zhí)行腳本一樣,分配給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中,使用腳本執(zhí)行,不用var或者let創(chuàng)建的變量會(huì)添加到global而不是this.
test.js foo = "bar"; console.log(this.foo); console.log(global.foo);
$ node test.js undefined bar
在repl中,它是分配到這兩個(gè)上的。
二. 函數(shù)中的this除了DOM事件處理程序或者一個(gè)thisArg已經(jīng)設(shè)置的情況外,在node和瀏覽器中,函數(shù)中(不實(shí)例化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會(huì)變?yōu)?b>underfined
當(dāng)你new一個(gè)函數(shù)的時(shí)候,this會(huì)成為一個(gè)新的上下文,不等同于全局this
三. 原型中的this函數(shù)對(duì)象有一個(gè)特殊的屬性prototype,當(dāng)你創(chuàng)建一個(gè)函數(shù)實(shí)例,可以訪問(wèn)prototype屬性,可以使用this進(jìn)行訪問(wèn)
function Thing() { console.log(this.foo); } Thing.prototype.foo = "bar"; var thing = new Thing(); //logs "bar" console.log(thing.foo); //logs "bar"
加入創(chuàng)建多個(gè)實(shí)例化,它們共享原型上的值,this.foo都會(huì)返回相同的值,除非你在實(shí)例化函數(shù)上進(jìn)行覆蓋。
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在一個(gè)實(shí)例中是一個(gè)特殊的對(duì)象,this實(shí)際是一個(gè)關(guān)鍵字,可以認(rèn)為this作為一種方法去訪問(wèn)prototype,直接分配給this,將會(huì)覆蓋原來(lái)prototype上的方法。你可以刪除this掛接的方法,從而恢復(fù)訪問(wèn)默認(rèn)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";
或者直接引用函數(shù)對(duì)象的原型。
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";
創(chuàng)建的實(shí)例都共享相同的屬性和方法,如果給prototype分配一個(gè)數(shù)組,所有實(shí)例都能夠訪問(wèn)。
function Thing() { } Thing.prototype.things = []; var thing1 = new Thing(); var thing2 = new Thing(); thing1.things.push("foo"); console.log(thing2.things); //logs ["foo"]
在prototype上分配一個(gè)數(shù)組通常是一個(gè)錯(cuò)誤,如果希望每個(gè)實(shí)例都有自己的數(shù)組,那在函數(shù)中創(chuàng)建。
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可以通過(guò)原型鏈找到相應(yīng)的方法。
function Thing1() { } Thing1.prototype.foo = "bar"; function Thing2() { } Thing2.prototype = new Thing1(); var thing = new Thing2(); console.log(thing.foo); //logs "bar"
在javascript中可以使用原型鏈模擬傳統(tǒng)面向?qū)ο罄^承。
使用函數(shù)內(nèi)含有綁定this的方法或者屬性去創(chuàng)建原型鏈,將會(huì)隱藏上層原型鏈定義的內(nèi)容。
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"
我喜歡叫綁定在原型上的函數(shù)為methods.在methods中使用this綁定某個(gè)值,將會(huì)覆蓋原型上的相關(guān)定義。
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嵌套函數(shù)中,雖然可以捕獲到父函數(shù)中的變量,但是不繼承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"
函數(shù)doIt中的this指向global,在use strict下則為undefined,這是很多不熟悉this用法的人痛苦的根源之一。
更壞的情況是,將一個(gè)實(shí)例方法作為參數(shù)傳入函數(shù)。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賦值給一個(gè)變量,通常叫self,能夠避免this指向global這個(gè)問(wèn)題。
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"
但是這種方法在將一個(gè)實(shí)例方法作為參數(shù)傳入函數(shù)情況下,不起作用
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
解決這個(gè)方法,可以使用函數(shù)綁定的方法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在新的上下文環(huán)境中調(diào)用方法或者函數(shù)。
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,適用于任何函數(shù)或方法,即使沒(méi)有在實(shí)例原型上定義。
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"
避免從構(gòu)造函數(shù)返回任何東西,因?yàn)樗赡軙?huì)替換所產(chǎn)生的實(shí)例。
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),返回語(yǔ)句將會(huì)被忽略。最好不要從你打算調(diào)用的構(gòu)造函數(shù)中返回任何東西,即使你知道你在做什么。如果你想創(chuàng)建一個(gè)工廠模式,使用一個(gè)函數(shù)來(lái)創(chuàng)建實(shí)例,不要用new的。當(dāng)然,這只是個(gè)人觀點(diǎn)。
避免使用new`,使用Object.create也能創(chuàng)建一個(gè)實(shí)例
function Thing() { } Thing.prototype.foo = "bar"; Thing.prototype.logFoo = function () { console.log(this.foo); } var thing = Object.create(Thing.prototype); thing.logFoo(); //logs "bar"
然而這不會(huì)調(diào)用構(gòu)造函數(shù)。
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"
因?yàn)?b>Object.create不會(huì)調(diào)用構(gòu)造函數(shù),所以這是一個(gè)有效的創(chuàng)建繼承模式的方法,能夠重寫(xiě)原型鏈上的構(gòu)造函數(shù)。
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();四. 對(duì)象中的this
可以在對(duì)象的任何函數(shù)中使用this來(lái)引用該對(duì)象上的其他屬性。這與使用new實(shí)例不同。
var obj = { foo: "bar", logFoo: function () { console.log(this.foo); } }; obj.logFoo(); //logs "bar"
不使用new,Object.create ,function 去創(chuàng)建一個(gè)對(duì)象,也可以像實(shí)例化一樣綁定到對(duì)象上。
var obj = { foo: "bar" }; function logFoo() { console.log(this.foo); } logFoo.apply(obj); //logs "bar"
當(dāng)你像下面使用this時(shí),沒(méi)有順著對(duì)象的層次結(jié)構(gòu)。只有直接父對(duì)象上的屬性才能通過(guò)this進(jìn)行訪問(wèn)
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
在一個(gè)HTML DOM event處理程序中,this通常是指DOM element event綁定的對(duì)象
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指向當(dāng)前的元素
this的覆蓋
你不能夠復(fù)寫(xiě)this,因?yàn)樗且粋€(gè)關(guān)鍵詞
function test () { var this = {}; // Uncaught SyntaxError: Unexpected token this }七. eavl中的this
可以使用eavl訪問(wèn)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訪問(wèn)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添加到當(dāng)前的范圍來(lái)讀取和寫(xiě)入值,而不用顯式調(diào)用。
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"
很多人認(rèn)為這是錯(cuò)的做法,鑒于with引起的歧義。
九. jQuery中的this像HTML DOM elements的事件處理程序一樣,jQuery在很多地方使用this指向DOM元素。比如$.each
鑒于筆者翻譯水平有限,有什么問(wèn)題歡迎提出指教。
十.參考資料原文地址:all this
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/80248.html
摘要:事件驅(qū)動(dòng)正是一種回調(diào)函數(shù)設(shè)計(jì)模式。由于不支持多線程,所以為了實(shí)現(xiàn)并行處理,不得不使用回調(diào)函數(shù),這逐漸成為了一種慣例。上面的回調(diào)函數(shù)只是單純的函數(shù)而不具有狀態(tài)。如果回調(diào)函數(shù)具有狀態(tài),就能得到更為廣泛的應(yīng)用。 回調(diào)函數(shù)模式 回調(diào)函數(shù)與控制反轉(zhuǎn) 回調(diào)函數(shù)是程序設(shè)計(jì)的一種方法。這種方法是指,在傳遞了可能會(huì)進(jìn)行調(diào)用的函數(shù)或?qū)ο笾螅谛枰獣r(shí)再分別對(duì)其進(jìn)行調(diào)用。由于調(diào)用方與被調(diào)用方的依賴(lài)關(guān)系與通常...
摘要:此時(shí)使用設(shè)置當(dāng)前值中的猜測(cè)值為輸入框的內(nèi)容值。接著判斷猜測(cè)之是否大于或者小于,因?yàn)檫@兩者是范圍之外不再進(jìn)行判斷,所以最開(kāi)始使用進(jìn)行判斷不能小于不能大于以上代碼中表示調(diào)用微信小程序接口彈出提示,傳入的參數(shù)為提示內(nèi)容。 ...
摘要:怎么樣好不好最近美國(guó)新的全解鎖原生段上架開(kāi)售,支持等,原一期產(chǎn)品可加價(jià)更換年付免費(fèi)更換,美國(guó)原生段仍有少量剩余,套餐原價(jià)基礎(chǔ)上每月加價(jià)元可更換美國(guó)原生,更換的為純凈新分配美國(guó)段,絕對(duì)傳家寶產(chǎn)品,支持解鎖美區(qū)游戲,,等,同時(shí)支持。lisahost怎么樣?lisahost好不好?lisahost最近美國(guó)新的全解鎖原生IP 206段上架開(kāi)售,支持tiktok等,原CN2一期產(chǎn)品可加價(jià)更換(年付免費(fèi)...
閱讀 3411·2023-04-25 20:37
閱讀 3152·2021-09-07 09:59
閱讀 1675·2019-08-29 12:43
閱讀 1195·2019-08-28 18:27
閱讀 489·2019-08-26 13:50
閱讀 2041·2019-08-26 10:33
閱讀 3602·2019-08-23 18:39
閱讀 2411·2019-08-23 18:09