淺談JavaScript中this的指向更改
JS中this指向的更改
JavaScript 中 this 的指向問(wèn)題 前面已經(jīng)總結(jié)過(guò),但在實(shí)際開(kāi)中, 很多場(chǎng)景都需要改變 this 的指向。 現(xiàn)在我們討論更改 this 指向的問(wèn)題。
call更改this指向
call 的使用語(yǔ)法:func.call(thisArg, arg1, arg2, ...)
call 方法需要一個(gè)指定的 this 值( this要指向的對(duì)象 )和一個(gè)或者多個(gè)參數(shù)。提供的 this 值會(huì)更改調(diào)用函數(shù)內(nèi)部的 this 指向。
// 使用 call 方法改變調(diào)用函數(shù)執(zhí)行上下文的 this 指向 var animal = '小貓'; var times = '15小時(shí)'; function greet() { let str = this.animal + '睡覺(jué)時(shí)間一般為:' + this.times; console.log(str); } var dogObj = { animal: '小狗', times: '8小時(shí)' }; var pigObj = { animal: '小豬', times: '13小時(shí)' } greet(); // 小貓睡覺(jué)時(shí)間一般為:15小時(shí) greet.call(dogObj); // 小狗睡覺(jué)時(shí)間一般為:8小時(shí) greet.call(pigObj); // 小豬睡覺(jué)時(shí)間一般為:13小時(shí) greet.call(); // 小貓睡覺(jué)時(shí)間一般為:15小時(shí)
當(dāng)直接調(diào)用函數(shù) greet 時(shí),函數(shù) greet 內(nèi)部的 this 指向的是全局對(duì)象 Window。
函數(shù) greet 調(diào)用 call() 方法并傳遞對(duì)象 dogObj 時(shí),函數(shù) greet 內(nèi)部的 this 就指向了對(duì)象 dogObj 。
函數(shù) greet 調(diào)用 call() 方法并傳遞對(duì)象 pigObj 時(shí),函數(shù) greet 內(nèi)部的 this 就指向了對(duì)象 pigObj 。
call()不傳參的話,在嚴(yán)格模式下,this 的值將會(huì)是 undefined;否則將會(huì)指向全局對(duì)象 Window。
匿名函數(shù)調(diào)用call方法:
var books = [{ name: 'CSS選擇器', price: 23 }, { name: 'CSS世界', price: 35 }, { name: 'JavaScript語(yǔ)言設(shè)計(jì)', price: 55 }]; for (var i = 0; i < books.length; i++) { (function (i) { // 這里this指向的是call綁定的數(shù)組的每一個(gè)元素對(duì)象 this.printf = function () { console.log(`${i} ${this.name}: ¥${this.price}`); } this.printf(); }).call(books[i], i); } // 打印結(jié)果如下: // 0 CSS選擇器: ¥23 // 1 CSS世界: ¥35 // 2 JavaScript語(yǔ)言設(shè)計(jì): ¥55
call實(shí)現(xiàn)繼承:
// 實(shí)現(xiàn)兩個(gè)數(shù)相加的構(gòu)造函數(shù) function CalcA(){ this.add = function(a, b){ return a + b; } } // 實(shí)現(xiàn)兩個(gè)數(shù)相減的構(gòu)造函數(shù) function CalcS(){ this.sub = function(a, b){ return a - b; } } // 計(jì)算構(gòu)造函數(shù) function Calc(){ console.log(this); // Calc {} CalcA.call(this); CalcS.call(this); console.log(this); // Calc {add: ƒ, sub: ƒ} } var calc = new Calc(); console.log(calc.add(2, 3)); // 5 console.log(calc.sub(10, 1));// 9
構(gòu)造函數(shù) Calc 通過(guò) call 方法使構(gòu)造函數(shù) CalcA、CalcS中的 this 指向了 Calc 自己,從而繼承了它們的屬性及方法。所以,構(gòu)造函數(shù) Calc 生成的實(shí)例對(duì)象也能夠訪問(wèn)構(gòu)造函數(shù) CalcA、CalcS中的屬性及方法。
apply方法更改this指向
apply 的使用語(yǔ)法:func.apply(thisArg, [argsArray])
apply 的用法與 call 方法類(lèi)似,只不過(guò) call 方法接受的是參數(shù)列表,而 apply 方法接受的是一個(gè)數(shù)組或者類(lèi)數(shù)組對(duì)象。上面的例子完全可以將 call 更換為 apply,只不過(guò) apply 方法只能接受兩個(gè)參數(shù),而且第二個(gè)參數(shù)是一個(gè)數(shù)組或者類(lèi)數(shù)組對(duì)象。
bind方法更改this指向
bind 的使用語(yǔ)法:func.bind(thisArg, arg1, arg2, ...)
bind 的參數(shù)與 call 相同,但是 bind 返回的是一個(gè)改變this指向后的函數(shù)實(shí)例。
var petalNum = 100; function Flower() { this.petalNum = Math.ceil(Math.random() * 10) + 1; } Flower.prototype.declare = function() { console.log(this); console.log('this is a beautiful flower with ' + this.petalNum + ' petals'); } Flower.prototype.bloom = function() { console.log(this); // Flower {petalNum: 7} // 如果不綁定 this 就會(huì)指向 Window 全局對(duì)象 window.setTimeout(this.declare, 1000); // bind 綁定 this,指向 Flower 的原型對(duì)象 window.setTimeout(this.declare.bind(this), 2000); } var flower = new Flower(); flower.bloom();
實(shí)例對(duì)象 flower 調(diào)用 bloom 方法后,bloom 內(nèi)的 this 指向構(gòu)造函數(shù)的原型對(duì)象。
1 秒后延遲函數(shù)調(diào)用構(gòu)造函數(shù)的 declare 方法, 此時(shí)執(zhí)行函數(shù) declare 中的 this 指向 Window 。打印的結(jié)果如下:
// Window {parent: Window, postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, …} // this is a beautiful flower with 100 petals
2 秒后延遲函數(shù)調(diào)用構(gòu)造函數(shù)的 declare 方法,此時(shí)執(zhí)行函數(shù) declare 通過(guò) bind 將 this(構(gòu)造函數(shù)的原型對(duì)象)綁定。打印的結(jié)果如下:
// 注意,此時(shí)petalNum的值時(shí)隨機(jī)取的。 // Flower {petalNum: 7} // this is a beautiful flower with 7 petals
這里將 bind換 成 call,apply 會(huì)導(dǎo)致立即執(zhí)行,延遲效果會(huì)失效。
ES6的箭頭函數(shù)更改this指向
箭頭函數(shù)中的 this 是在定義函數(shù)的時(shí)候綁定,而不是在執(zhí)行函數(shù)的時(shí)候綁定。 所謂定義時(shí)候綁定,就是指 this 是繼承自父執(zhí)行上下文的 this。
var a = 1; var obj = { a: 2, f1: function(){ console.log(this.a) }, f2: () => { console.log(this.a) } } obj.f1(); // 2 obj.f2(); // 1
obj.f1() 執(zhí)行后打印的是 2,這里好理解,obj 調(diào)用 f1 函數(shù),那么函數(shù)中的 this 就指向調(diào)用對(duì)象 obj??梢钥闯觯@里 this 是在執(zhí)行函數(shù)的時(shí)候綁定的。
obj.f2() 執(zhí)行后打印的是 1。f2 是箭頭函數(shù),那么函數(shù)中的 this 是繼承自父執(zhí)行上下文的 this。這里箭頭函數(shù)的父級(jí)是對(duì)象 obj,obj 的執(zhí)行上下文就是全局對(duì)象 Window,那么箭頭函數(shù)中的 this 就指向了全局對(duì)象了。
再看一個(gè)例子:
var a = 11; function test() { this.a = 22; let b = () => { console.log(this.a) } b(); } test(); // 22
按著定義的理解,應(yīng)該打印出 11 才對(duì)呀,因?yàn)榧^函數(shù)父級(jí)的執(zhí)行上下文就是 Window 全局對(duì)象,此時(shí)打印的是全局對(duì)象的 a。
先不要著急,先慢慢分析,上面的分析是對(duì)的,箭頭函數(shù)的 this 就是指向 Window 對(duì)象。test 函數(shù)在全局環(huán)境下調(diào)用時(shí)其內(nèi)部的 this 就指向了全局 Window 對(duì)象,代碼中的 this.a = 22;
就將全局中的 a 重新賦值了,所以箭頭函數(shù)在全局對(duì)象中找到的 a 值就是 22。我們可以在控制臺(tái)上輸入 window.a 查看全局對(duì)象中的 a 值,結(jié)果打印 22,所以我們就不難理解箭頭函數(shù)中打印的結(jié)果為什么是 22 了。如果將代碼中的 this.a = 22;
修改為 var a = 22;
,那么箭頭函數(shù)中打印的結(jié)果就是 11 了。
箭頭函數(shù)會(huì)繼承外層函數(shù)調(diào)用的 this 綁定,這和 var self = this;
的綁定機(jī)制一樣。箭頭函數(shù)中,this 指向固定化,箭頭函數(shù)根本就沒(méi)有自己的 this, 所以也就不能用作構(gòu)造函數(shù)使用了。
到此這篇關(guān)于淺談JavaScript中this的指向更改的文章就介紹到這了,更多相關(guān)JavaScript中this指向更改內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
javascript計(jì)算星座屬相(十二生肖屬相)示例代碼
本文介紹了使用javascript計(jì)算星座和屬相的示例,這個(gè)可以用在用戶注冊(cè)的時(shí)候顯示出來(lái),大家參考使用吧2014-01-01深入理解JavaScript中async/await的錯(cuò)誤處理方式
在現(xiàn)代JavaScript開(kāi)發(fā)中,異步編程是不可或缺的一部分,async和await是一種強(qiáng)大的異步編程工具,它們使得編寫(xiě)和維護(hù)異步代碼更加容易和清晰,然而,異步操作仍然可能會(huì)出現(xiàn)錯(cuò)誤,本文將深入探討async和await的錯(cuò)誤處理方式,提供詳細(xì)的代碼示例和解釋2023-09-09js判斷輸入是否為正整數(shù)、浮點(diǎn)數(shù)等數(shù)字的函數(shù)代碼
js判斷輸入是否為正整數(shù)、浮點(diǎn)數(shù)等數(shù)字的函數(shù)代碼,學(xué)習(xí)js的朋友可以參考下。2010-11-11js自執(zhí)行函數(shù)的幾種不同寫(xiě)法的比較
js自執(zhí)行函數(shù)的幾種不同寫(xiě)法的比較,需要的朋友可以參考下2012-08-08詳解webpack+ES6+Sass搭建多頁(yè)面應(yīng)用
這篇文章主要介紹了webpack+ES6+Sass搭建多頁(yè)面應(yīng)用,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-11-11JavaScript實(shí)現(xiàn)抽獎(jiǎng)器效果
這篇文章主要為大家詳細(xì)介紹了JavaScript實(shí)現(xiàn)抽獎(jiǎng)器效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-10-10JavaScript中json對(duì)象和string對(duì)象之間相互轉(zhuǎn)化
json對(duì)象和string對(duì)象之間的轉(zhuǎn)化已經(jīng)成為了大家耳熟能詳?shù)脑掝},本人今天就多啰嗦一些他們之間的故事,如有不對(duì)之處,還請(qǐng)各位海涵呢?不多說(shuō)了直切主題2012-12-12JS/jQuery判斷DOM節(jié)點(diǎn)是否存在的簡(jiǎn)單方法
下面性價(jià)比就為大家?guī)?lái)一篇JS/jQuery判斷DOM節(jié)點(diǎn)是否存在的簡(jiǎn)單方法。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起 小編過(guò)來(lái)看看吧2016-11-11js實(shí)現(xiàn)表單項(xiàng)的全選、反選及刪除操作示例
這篇文章主要介紹了js實(shí)現(xiàn)表單項(xiàng)的全選、反選及刪除操作,結(jié)合實(shí)例形式分析了基于dedecms后臺(tái)使用js實(shí)現(xiàn)表單項(xiàng)的全選、反選及刪除相關(guān)操作技巧,需要的朋友可以參考下2020-06-06