摘要:在等面向?qū)ο蟮恼Z言中,關(guān)鍵字的含義是明確且具體的,即指代當(dāng)前對(duì)象。一般在編譯期確定下來,或稱為編譯期綁定。無論是用還是這種方式,都取決于傳入該函數(shù)的對(duì)象。使用方法綁定使用在創(chuàng)建時(shí)綁定指針。如果是行內(nèi)的事件監(jiān)聽者,指針會(huì)被設(shè)置為其所在的元素
this
在 Java 等面向?qū)ο蟮恼Z言中,this 關(guān)鍵字的含義是明確且具體的,即指代當(dāng)前對(duì)象。一般在編譯期確定下來,或稱為編譯期綁定。而在 JavaScript 中,this 是動(dòng)態(tài)綁定,或稱為運(yùn)行期綁定的,這就導(dǎo)致 JavaScript 中的 this 關(guān)鍵字有能力具備多重含義,變得有點(diǎn)隨意。而在ES6中又引入了Arrow Function以及Class,它們對(duì)于this指針也帶來了一定的影響。
Global Context(全局上下文)在任何函數(shù)之外的全局環(huán)境中,不管在不在strict模式中,this指針往往指向一個(gè)全局變量。
console.log(this.document === document); // true // In web browsers, the window object is also the global object: console.log(this === window); // true this.a = 37; console.log(window.a); // 37Function Context(函數(shù)上下文) 簡(jiǎn)單調(diào)用
在某個(gè)函數(shù)中,this的值取決于該函數(shù)的調(diào)用者。無論是用hello("world”)還是call這種方式,都取決于傳入該函數(shù)的對(duì)象。不過,在ES5的嚴(yán)格或者不嚴(yán)格模式下,同樣的調(diào)用方式會(huì)有不同的結(jié)果。
function hello(thing) { console.log("Hello " + thing); } // this: hello("world") // desugars to: hello.call(window, "world");
而如果是strict模式下:
// this: hello("world") // desugars to: hello.call(undefined, "world");對(duì)象方法
另一種常用的調(diào)用函數(shù)的方法就是在object中調(diào)用:
function hello(thing) { console.log(this + " says hello " + thing); } person = { name: "Brendan Eich" } person.hello = hello; person.hello("world") // still desugars to person.hello.call(person, "world") [object Object] says hello world hello("world") // "[object DOMWindow]world"bind
很多時(shí)候,需要為某個(gè)函數(shù)指定一個(gè)固定的this對(duì)象,最簡(jiǎn)單的方式即是使用閉包來獲取一個(gè)不變的this對(duì)象。
var person = { name: "Brendan Eich", hello: function(thing) { console.log(this.name + " says hello " + thing); } } var boundHello = function(thing) { return person.hello.call(person, thing); } boundHello("world");
不過,這種方式仍然存在著一定的問題,ES5為Function對(duì)象引入了一個(gè)新的bind方法來解決這個(gè)問題:
var boundHello = person.hello.bind(person); boundHello("world") // "Brendan Eich says hello world"
這種方式在設(shè)置回調(diào)函數(shù)中的this指針的時(shí)候會(huì)起到很大的作用,特別是在React中,為了保證指針的穩(wěn)定性,往往需要為內(nèi)置方法設(shè)置bind。
var person = { name: "Alex Russell", hello: function() { console.log(this.name + " says hello world"); } } $("#some-div").click(person.hello.bind(person)); // when the div is clicked, "Alex Russell says hello world" is printedapply/call
在 JavaScript 中函數(shù)也是對(duì)象,對(duì)象則有方法,apply 和 call 就是函數(shù)對(duì)象的方法。這兩個(gè)方法異常強(qiáng)大,他們?cè)试S切換函數(shù)執(zhí)行的上下文環(huán)境(context),即 this 綁定的對(duì)象。很多 JavaScript 中的技巧以及類庫都用到了該方法。讓我們看一個(gè)具體的例子:
function Point(x, y){ this.x = x; this.y = y; this.moveTo = function(x, y){ this.x = x; this.y = y; } } var p1 = new Point(0, 0); var p2 = {x: 0, y: 0}; p1.moveTo(1, 1); p1.moveTo.apply(p2, [10, 10]);array.forEach
在這樣一個(gè)回調(diào)函數(shù)中,回調(diào)函數(shù)的this指針是由調(diào)用者決定的,完整的forEach聲明如下:array.forEach(callback[, thisArg]),這個(gè)傳入的thisArg即是回調(diào)的調(diào)用者。
var o={ v:"hello", p:["a1","a2"], f:function f(){ this.p.forEach(function (item){ console.log(this.v+" "+item); }); } } o.f(); //undefined a1 //undefined a2Arrow Function
Arrow Function是ES6新增的特性,很類似于Java或者C#中的Lambda表達(dá)式。Arrow函數(shù)中的this指針在創(chuàng)建時(shí)就被綁定到了閉合的作用域內(nèi),不會(huì)收到new、bind、call以及apply這些方法的影響。
var o = { traditionalFunc: function () { // Normal function, bound as expected console.log("traditionalFunc this === o?", this === o); }, arrowFunc: () => { // Arrow function, bound to scope where it"s created console.log("arrowFunc this === o?", this === o); console.log("arrowFunc this === window?", this === window); } }; o.traditionalFunc(); // traditionalFunc this === o? true o.arrowFunc(); // arrowFunc this === o? false // arrowFunc this === window? true
上述代碼中的arrowFunc隸屬于o對(duì)象,但是在window的作用域中被創(chuàng)建,因此,最終arrow函數(shù)中的this指針的值等于window對(duì)象。ES5中的對(duì)于this的控制已然非常復(fù)雜,特別是在處理異步代碼中如何傳入合適的this對(duì)象也是一件麻煩事,如下文所示:
var asyncFunction = (param, callback) => { window.setTimeout(() => { callback(param); }, 1); }; // With a traditional function if we don"t control // the context then can we lose control of `this`. var o = { doSomething: function () { // Here we pass `o` into the async function, // expecting it back as `param` asyncFunction(o, function (param) { // We made a mistake of thinking `this` is // the instance of `o`. console.log("param === this?", param === this); }); } }; o.doSomething(); // param === this? false
為了綁定上述代碼中的this指針,一般來說有三個(gè)辦法:
為this指針創(chuàng)建一個(gè)固定的引用。
var asyncFunction = (param, callback) => { window.setTimeout(() => { callback(param); }, 1); }; // Define a reference to `this` outside of the callback, // but within the callback"s lexical scope var o = { doSomething: function () { var self = this; // Here we pass `o` into the async function, // expecting it back as `param` asyncFunction(o, function (param) { console.log("param === this?", param === self); }); } }; o.doSomething(); // param === this? true
使用bind方法綁定this
var asyncFunction = (param, callback) => { window.setTimeout(() => { callback(param); }, 1); }; // Here we control the context of the callback using // `bind` ensuring `this` is correct var o = { doSomething: function () { // Here we pass `o` into the async function, // expecting it back as `param` asyncFunction(o, function (param) { console.log("param === this?", param === this); }.bind(this)); } }; o.doSomething(); // param === this? true
使用Arrow Function在創(chuàng)建時(shí)綁定this指針。
var asyncFunction = (param, callback) => { window.setTimeout(() => { callback(param); }, 1); }; var o = { doSomething: function () { // Here we pass `o` into the async function, // expecting it back as `param`. // // Because this arrow function is created within // the scope of `doSomething` it is bound to this // lexical scope. asyncFunction(o, (param) => { console.log("param === this?", param === this); }); } }; o.doSomething(); // param === this? trueDOM Event handler(Dom事件)
當(dāng)某個(gè)函數(shù)作為事件監(jiān)聽器時(shí),它的this值往往被設(shè)置為它的調(diào)用者。
// When called as a listener, turns the related element blue function bluify(e){ // Always true console.log(this === e.currentTarget); // true when currentTarget and target are the same object console.log(this === e.target); this.style.backgroundColor = "#A5D9F3"; } // Get a list of every element in the document var elements = document.getElementsByTagName("*"); // Add bluify as a click listener so when the // element is clicked on, it turns blue for(var i=0 ; i如果是行內(nèi)的事件監(jiān)聽者,this指針會(huì)被設(shè)置為其所在的DOM元素:
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/86029.html
摘要:擴(kuò)展運(yùn)算符是以下簡(jiǎn)稱中又一非常好用的實(shí)戰(zhàn)技術(shù)它的寫法只需要三個(gè)點(diǎn)作用則顧名思義用來展開你想要使用的任意變量本質(zhì)上是對(duì)所有擁有迭代器接口的對(duì)象進(jìn)行迭代。 擴(kuò)展運(yùn)算符(spreading)是 ECMASCRIPT 6(以下簡(jiǎn)稱ES 6) 中又一非常好用的實(shí)戰(zhàn)技術(shù), 它的寫法只需要三個(gè)點(diǎn)(...),作用則顧名思義,用來展開你想要使用的任意變量,本質(zhì)上是對(duì)所有擁有迭代器接口(Iterator)...
摘要:相信解構(gòu)賦值自以下簡(jiǎn)稱面世以來被大家快速地熟悉并運(yùn)用到實(shí)際開發(fā)中了這是一種能有效減少代碼量,使代碼邏輯更簡(jiǎn)單優(yōu)雅的技術(shù)下面我們就再來回顧總結(jié)一下解構(gòu)賦值的種種用法吧基本用法從對(duì)象解構(gòu)假設(shè)有一個(gè)對(duì)象,它的結(jié)構(gòu)為以對(duì)稱的形式從從邊的對(duì)象中匹配與 相信解構(gòu)賦值(Destructuring)自 ECMASCRIPT 6(以下簡(jiǎn)稱 ES 6) 面世以來被大家快速地熟悉并運(yùn)用到實(shí)際開發(fā)中了, 這是...
摘要:前端培訓(xùn)初級(jí)階段語法變量值類型運(yùn)算符語句前端培訓(xùn)初級(jí)階段內(nèi)置對(duì)象函數(shù)前端培訓(xùn)初級(jí)階段類模塊繼承基礎(chǔ)內(nèi)容知識(shí)我們會(huì)用到。 前端最基礎(chǔ)的就是 HTML+CSS+Javascript。掌握了這三門技術(shù)就算入門,但也僅僅是入門,現(xiàn)在前端開發(fā)的定義已經(jīng)遠(yuǎn)遠(yuǎn)不止這些。前端小課堂(HTML/CSS/JS),本著提升技術(shù)水平,打牢基礎(chǔ)知識(shí)的中心思想,我們開課啦(每周四)。 該文為前端培訓(xùn)-初級(jí)階段(1...
摘要:執(zhí)行函數(shù)調(diào)用規(guī)范中的第一步是一個(gè)明顯的賦值語句,我們查看規(guī)范,賦值語句會(huì)發(fā)生什么可以看出簡(jiǎn)單賦值語句返回的是對(duì)等于號(hào)右邊進(jìn)行之后的結(jié)果,上一節(jié)講了,執(zhí)行過就會(huì)返回的類型,此處會(huì)返回也就是一個(gè)類型。 前言 this是JavaScript中的著名月經(jīng)題,每隔一段時(shí)間就有人翻出了拿各種奇怪的問題出來討論,每次都會(huì)引發(fā)一堆口水之爭(zhēng)。從搜索引擎搜了一下現(xiàn)在的比較熱門的關(guān)于this的用法,如:Ja...
摘要:插件開發(fā)前端掘金作者原文地址譯者插件是為應(yīng)用添加全局功能的一種強(qiáng)大而且簡(jiǎn)單的方式。提供了與使用掌控異步前端掘金教你使用在行代碼內(nèi)優(yōu)雅的實(shí)現(xiàn)文件分片斷點(diǎn)續(xù)傳。 Vue.js 插件開發(fā) - 前端 - 掘金作者:Joshua Bemenderfer原文地址: creating-custom-plugins譯者:jeneser Vue.js插件是為應(yīng)用添加全局功能的一種強(qiáng)大而且簡(jiǎn)單的方式。插....
閱讀 3057·2021-11-25 09:43
閱讀 1653·2021-11-24 11:15
閱讀 2373·2021-11-22 15:25
閱讀 3522·2021-11-11 16:55
閱讀 3257·2021-11-04 16:10
閱讀 2790·2021-09-14 18:02
閱讀 1698·2021-09-10 10:50
閱讀 1085·2019-08-29 15:39