摘要:構(gòu)造函數(shù)也是函數(shù),所以當(dāng)你用普通調(diào)用方式調(diào)用時(shí)這個(gè)時(shí)候相當(dāng)于給對(duì)象添加了和兩個(gè)屬性。為構(gòu)造函數(shù)指定這里報(bào)錯(cuò)了,原因是我們?nèi)チ撕瘮?shù),這里的函數(shù)不是一個(gè)構(gòu)造函數(shù)當(dāng)然解決方式也是有的。
前言
他是個(gè)啥javascript中的this是啥東西?為啥我們經(jīng)常被他搞得暈頭轉(zhuǎn)向不知所以?他是惡魔?是天使 ?是怪胎?讓我們一起來揭開它那神秘的面紗。
首先this是Javascript語言的關(guān)鍵字之一,指函數(shù)運(yùn)行時(shí)的當(dāng)前對(duì)象。那既然和函數(shù)運(yùn)行有關(guān),js中函數(shù)有哪些調(diào)用模式呢?
純粹的函數(shù)調(diào)用
對(duì)象的方法調(diào)用
構(gòu)造函數(shù)調(diào)用
apply、call調(diào)用
我擦,有木有一千只草泥馬在心里蹦騰不息,人家是要弄懂this,你這又是整的哪一出
我們慢慢來,一步步從這些調(diào)用模式中探究this這個(gè)神奇的遠(yuǎn)古神獸
純粹的函數(shù)調(diào)用函數(shù)調(diào)用 即 functionName () 模式,這也是我們使用的最多的一種方式,其屬于全局調(diào)用,瀏覽中默認(rèn)情況下函數(shù)內(nèi)部的this指向window,當(dāng)然是在非嚴(yán)格模式下。
this.name = "qianlong"; function showName () { console.log(this.name); console.log(this === window); } showName() // qianlong // true對(duì)象的方法調(diào)用
當(dāng)一個(gè)函數(shù)作為對(duì)象的某個(gè)屬性方法被調(diào)用的時(shí)候
var obj = { name: "qianlong", showName: function () { console.log(this.name); } }; obj.showName(); // qianlong
可以看出this指向是obj這個(gè)對(duì)象,其實(shí)本質(zhì)上講函數(shù)調(diào)用形式內(nèi)部this就是指向調(diào)用它的那個(gè)對(duì)象
上面的例子相當(dāng)于
window.showName()
這也是為什么可以讀取到全局定義的name屬性的原因。
再來
var showName = function () { console.log(this.name); }, obj = { name: "qianlong", showName: showName }; obj.showName();
這個(gè)時(shí)候輸出的是什么呢
結(jié)果是不變的,在js中,一切都是對(duì)象,而這里也只是將,obj的showName屬性指向,showNmae函數(shù)的引用地址。
繼續(xù)
當(dāng)我們把showName方法賦值給了一個(gè)變量,又會(huì)有什么事情發(fā)生呢?
var obj = { name: "qianlong", showName: function () { console.log(this.name); } }; var tempShowName = obj.showName; tempShowName() // undefined
為什么不是期望的那樣輸出 qianlong呢。obj的showName方法是一個(gè)對(duì)象,當(dāng)把它賦值給了tempShowName變量,此時(shí)便和obj沒有什么關(guān)系了,而這個(gè)時(shí)候的調(diào)用和下面是等價(jià)的。
window.tempShowName()
window上此事并沒有name屬性,自然輸出是undefined。
構(gòu)造函數(shù)調(diào)用當(dāng)使用 new 去調(diào)用一個(gè)構(gòu)造函數(shù)的時(shí)候,內(nèi)部的this,指向的是實(shí)例化出來的對(duì)象。
var Person = function (name, sex) { this.name = name; this.sex = sex; console.log(this); }; var p1 = new Person("qianlong", "boy"); // Person {name: "qianlong", sex: "boy"};
構(gòu)造函數(shù)也是函數(shù),所以當(dāng)你用普通調(diào)用方式調(diào)用時(shí)
var Person = function (name, sex) { this.name = name; this.sex = sex; console.log(this); }; Person("qianlong", "boy"); // 這個(gè)時(shí)候相當(dāng)于給window對(duì)象添加了name和sex兩個(gè)屬性。 window.name // "qianlong" window.sex // "boy"apply、call調(diào)用
使用call和apply方式去調(diào)用一個(gè)函數(shù)的時(shí)候,內(nèi)部的this指向的是傳進(jìn)來的第一個(gè)參數(shù),當(dāng)?shù)谝粋€(gè)參數(shù)是undefined或者null的時(shí)候,依舊指向window
關(guān)于call和apply歡迎查看另一篇文章
js中call、apply、bind那些事
var showName = function () { console.log(this); }; showName() // window showName.call(undefined) // window showName.call(null) // window showName.call({name: "qianlong"}) // {name: "qianlong"}箭頭函數(shù)
在 ES6 的新規(guī)范中,加入了箭頭函數(shù),它和普通函數(shù)最不一樣的一點(diǎn)就是 this 的指向,普通函數(shù)中的this,是運(yùn)行時(shí)候決定的,而箭頭函數(shù)卻是定義時(shí)候就決定了。
var obj = { name: "qianlong", showName: function () { console.log(this.name); }, showNameLater: function () { setTimeout(() => { console.log(this.name); }, 1000) } }; obj.showNameLater(); // qianlong
var obj = { name: "qianlong", showName: () => { console.log(this.name); } }; obj.showName(); // undefined一些坑
1. setTimeout
var obj = { name: "qianlong", showName: function () { console.log(this.name); }, showNameLater: function () { setTimeout(this.showName, 1000); } }; obj.showNameLater(); // undefined
這里在執(zhí)行setTimeout這個(gè)函數(shù)的時(shí)候傳了obj的showName函數(shù)作為第一個(gè)參數(shù),其效果與
var showName = obj.showName
是相同的。而setTimeout內(nèi)部其實(shí)也是執(zhí)行了傳進(jìn)去這個(gè)函數(shù)而已,即。
showName();
還記得這種調(diào)用方式和window.showName()是類似的效果嗎?這個(gè)時(shí)候輸入為undefined也就好理解了。
那么怎么解決這個(gè)問題呢,畢竟我們期望的效果是輸出qianlong。
var obj = { name: "qianlong", showName: function () { console.log(this.name); }, showNameLater: function () { var self = this; setTimeout(function () { self.showName(); }, 1000); } }; obj.showNameLater();
或者
var obj = { name: "qianlong", showName: function () { console.log(this.name); }, showNameLater: function () { setTimeout(this.showName.bind(this), 1000); } }; obj.showNameLater();
2. setTimeout
尼瑪坑爹啊,居然還是因?yàn)槟恪?/p>
"use strict"; function show() { console.log(this); } show(); // undefined setTimeout(show, 1); // window
在嚴(yán)格模式下面,函數(shù)調(diào)用的時(shí)候沒有指定this的情況下,內(nèi)部this的表現(xiàn)為undefined,但是setTimeout卻不同,其內(nèi)部默認(rèn)還是指向window。
3. 為構(gòu)造函數(shù)指定this
var Person = function (name, sex) { this.name = name; this.sex = sex; }; var p1 = new Person.call({}); // Uncaught TypeError: Person.call is not a constructor
這里報(bào)錯(cuò)了,原因是我們?nèi)?new 了 Person.call 函數(shù) ,這里的函數(shù)不是一個(gè)構(gòu)造函數(shù);
當(dāng)然解決方式也是有的。
var Person = function (name, sex) { this.name = name; this.sex = sex; }; var p1 = new (Person.bind({}))("qianlong", "sex"); // Person {name: "qianlong", sex: "sex"}
4. 為箭頭函數(shù)指定this
var show = (str) => { console.log(str); console.log(this); }; show("qianlong"); // qianlong // window show.call({name: "qianlong"}, "qianlong"); // qianlong // window
可以看到使用call來手動(dòng)改變箭頭函數(shù)中的this的時(shí)候,無法成功。 箭頭函數(shù)中的 this 在定義它的時(shí)候已經(jīng)決定了(執(zhí)行定義它的作用域中的 this),與如何調(diào)用以及在哪里調(diào)用它無關(guān),包括 (call, apply, bind) 等操作都無法改變它的 this。
結(jié)語文章可能有些疏漏與錯(cuò)誤之處,歡迎各位指正。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/86732.html
摘要:瀏覽器緩存的分類瀏覽器緩存主要有兩類緩存協(xié)商和徹底緩存,也有稱之為協(xié)商緩存和強(qiáng)緩存。只能被終端用戶的瀏覽器緩存,不允許等中繼緩存服務(wù)器對(duì)其緩存。 今天小微開店寶在測(cè)試環(huán)境發(fā)布更新的時(shí)候,同事問:為什么我需要手動(dòng)清理瀏覽器緩存才能看到變更?難道系統(tǒng)上線后也需要客戶自己清理瀏覽器緩存嗎!看來,這個(gè)坑需要我來填了。 什么是瀏覽器緩存 瀏覽器緩存(Brower Caching)是瀏覽器在本地磁...
摘要:比如就會(huì)報(bào)出警告,并執(zhí)行出錯(cuò)。視頻的寬高,并不會(huì)因?yàn)樘顚懙臄?shù)值比例不合法而失真。通過綁定事件,來獲取視頻片段數(shù)據(jù),并在內(nèi)存中累積。執(zhí)行之后會(huì)停止觸發(fā)事件。錄制結(jié)束后,把累計(jì)的片段數(shù)據(jù)保存為對(duì)象,并從瀏覽器下載存為視頻文件。 前言 HTML5的權(quán)限越來越大了,瀏覽器可以直接調(diào)用攝像頭、麥克風(fēng)了,好激動(dòng)啊。我們要用純潔的HTML代碼造出自己的天地。 視頻采集 本篇介紹的栗子 都是在chro...
摘要:年已經(jīng)過去,這一年前端領(lǐng)域發(fā)生了什么有哪些技術(shù)和項(xiàng)目引人注目工程師們觀點(diǎn)和看法又有怎樣的變化在此,整理了一些對(duì)過去的年盤點(diǎn)的資料,一是希望能借此提高自己的姿勢(shì)水平,二是希望能為年的學(xué)習(xí)有所指導(dǎo)。 2016年已經(jīng)過去,這一年前端領(lǐng)域發(fā)生了什么?有哪些技術(shù)和項(xiàng)目引人注目?工程師們觀點(diǎn)和看法又有怎樣的變化?在此,整理了一些對(duì)過去的2016年盤點(diǎn)的資料,一是希望能借此提高自己的姿勢(shì)水平,二是希...
摘要:理解的函數(shù)基礎(chǔ)要搞好深入淺出原型使用原型模型,雖然這經(jīng)常被當(dāng)作缺點(diǎn)提及,但是只要善于運(yùn)用,其實(shí)基于原型的繼承模型比傳統(tǒng)的類繼承還要強(qiáng)大。中文指南基本操作指南二繼續(xù)熟悉的幾對(duì)方法,包括,,。商業(yè)轉(zhuǎn)載請(qǐng)聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請(qǐng)注明出處。 怎樣使用 this 因?yàn)楸救藢儆趥吻岸?,因此文中只看懂?8 成左右,希望能夠給大家?guī)韼椭?...(據(jù)說是阿里的前端妹子寫的) this 的值到底...
閱讀 2289·2019-08-30 15:56
閱讀 3121·2019-08-30 13:48
閱讀 1137·2019-08-30 10:52
閱讀 1508·2019-08-29 17:30
閱讀 433·2019-08-29 13:44
閱讀 3572·2019-08-29 12:53
閱讀 1129·2019-08-29 11:05
閱讀 2680·2019-08-26 13:24