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