成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專欄INFORMATION COLUMN

JavaScript中的this

SimpleTriangle / 2674人閱讀

摘要:作為構(gòu)造函數(shù)何為構(gòu)造函數(shù)所謂構(gòu)造函數(shù)就是用來對(duì)象的函數(shù),像等都是全局定義的構(gòu)造函數(shù)。正在跑步正在說話正在跑步正在說話如上,如果函數(shù)作為構(gòu)造函數(shù)用,那么其中的就代表它即將出來的對(duì)象。

前言

總括:詳解JavaScript中的this的一篇總結(jié),不懂this這個(gè)難點(diǎn),很多時(shí)候會(huì)造成一些困擾,寫出一些bug不知如何收?qǐng)?,所以一起來寫bug吧,不對(duì),一起來寫代碼吧。

原文地址:JavaScript中的this

知乎專欄: 前端進(jìn)擊者

博主博客地址:Damonare的個(gè)人博客

人生得意須盡歡,莫使金樽空對(duì)月

正文

? JavaScript中的this格外的不一樣,比如Java語言中的this是在代碼的執(zhí)行階段是不可更改,而JavaScript的this是在調(diào)用階段進(jìn)行綁定。?因?yàn)檫@一性質(zhì)所以給了this很大的發(fā)揮空間。但其在嚴(yán)格模式和非嚴(yán)格模式下又有些不一樣,在函數(shù)的不同調(diào)用方式也導(dǎo)致this有些區(qū)別。?

What"s this?

?首先對(duì)this的下個(gè)定義:this是在執(zhí)行上下文創(chuàng)建時(shí)確定的一個(gè)在執(zhí)行過程中不可更改的變量。

所謂執(zhí)行上下文,就是JavaScript引擎在執(zhí)行一段代碼之前將代碼內(nèi)部會(huì)用到的一些變量、函數(shù)this提前聲明然后保存在變量對(duì)象中的過程。這個(gè)"代碼片段"包括:全局代碼(script標(biāo)簽內(nèi)部的代碼)、函數(shù)內(nèi)部代碼、eval內(nèi)部代碼。而我們所熟知的作用域鏈也會(huì)在保存在這里,以一個(gè)類數(shù)組的形式存儲(chǔ)在對(duì)應(yīng)函數(shù)的[[Scopes]]屬性中。

this只在函數(shù)調(diào)用階段確定,也就是執(zhí)行上下文創(chuàng)建的階段進(jìn)行賦值,保存在變量對(duì)象中。這個(gè)特性也導(dǎo)致了this的多變性:?即當(dāng)函數(shù)在不同的調(diào)用方式下都可能會(huì)導(dǎo)致this的值不同。

??上面我們說過了在嚴(yán)格模式下和非嚴(yán)格模式下this表現(xiàn)不同:

var a = 1;
function fun() {
   "use strict";
    var a = 2;
      return this.a;
}
fun();//?報(bào)錯(cuò) Cannot read property "a" of undefined

?嚴(yán)格模式下,this指向undefined;

var a = 1;
function fun() {
    var a = 2;
      return this.a;
}
fun();//1

?非嚴(yán)格模式下this指向window;

上面同一段代碼,在不同模式下之所以有不同表現(xiàn),就是因?yàn)閠his在嚴(yán)格模式,非嚴(yán)格模式下的不同。

結(jié)論:當(dāng)函數(shù)獨(dú)立調(diào)用的時(shí)候,在嚴(yán)格模式下它的this指向undefined,在非嚴(yán)格模式下,當(dāng)this指向undefined的時(shí)候,自動(dòng)指向全局對(duì)象(瀏覽器中就是window)

多提一句,在全局環(huán)境下,this就是指向自己,再看?:

this.a = 1;
var b = 1;
c = 1;
console.log(this === window)//true
//這三種都能得到想要的結(jié)果,全局上下文的變量對(duì)象中存在這三個(gè)變量

再多提一句,當(dāng)this不在函數(shù)中用的時(shí)候會(huì)怎樣?看?:

var a = 1000;
var obj = {
    a: 1,
      b: this.a + 1
}
function fun() {
    var obj = {
          a: 1,
        c: this.a + 2 //嚴(yán)格模式下這塊報(bào)錯(cuò) Cannot read property "a" of undefined
    }
    return obj.c;
}
console.log(fun());//1002
console.log(obj.b);//1001

這種情況下this還是指向了window。那么我們可以多帶帶下個(gè)結(jié)論:

當(dāng)obj在全局聲明的時(shí)候,obj內(nèi)部屬性中的this指向全局對(duì)象,當(dāng)obj在一個(gè)函數(shù)中聲明的時(shí)候,嚴(yán)格模式下this會(huì)指向undefined,非嚴(yán)格模式自動(dòng)轉(zhuǎn)為指向全局對(duì)象。

?好了,剛剛小試牛刀下,知道了嚴(yán)格模式和非嚴(yán)格模式下this的區(qū)別,然而我們?nèi)粘?yīng)用最多的還是在函數(shù)中用this,上面也說過了this在函數(shù)的不同調(diào)用方式還有區(qū)別,那么函數(shù)的調(diào)用方式都有哪些呢?四種:

在全局環(huán)境或是普通函數(shù)中直接調(diào)用

作為對(duì)象的方法

使用apply和call

作為構(gòu)造函數(shù)

下面分別就四種情況展開:

直接調(diào)用

上面的?其實(shí)就是直接調(diào)用的,不過我決定再寫???:

var a = 1;
var obj  =  {
    a: 2,
      b: function () {
        function fun() {
          return this.a
        }
       console.log(fun());
    }
} 
obj.b();//1

fun函數(shù)雖然在obj.b方法中定義,但它還是一個(gè)普通函數(shù),直接調(diào)用在非嚴(yán)格模式下指向undefined,又自動(dòng)指向了全局對(duì)象,正如預(yù)料,嚴(yán)格模式會(huì)報(bào)錯(cuò)undefined.a不成立,a未定義。

重要的事情再說一遍:當(dāng)函數(shù)獨(dú)立調(diào)用的時(shí)候,在嚴(yán)格模式下它的this指向undefined,在非嚴(yán)格模式下,當(dāng)this指向undefined的時(shí)候,自動(dòng)指向全局對(duì)象(瀏覽器中就是window)。?

作為對(duì)象的方法
var a = 1;
var obj = {
  a: 2,
  b: function() {
    return this.a;
  }
}
console.log(obj.b())//2

?b所引用的匿名函數(shù)作為obj的一個(gè)方法調(diào)用,這時(shí)候this指向調(diào)用它的對(duì)象。這里也就是obj。那么如果b方法不作為對(duì)象方法調(diào)用呢?啥意思呢,就是這樣?:

var a = 1;
var obj = {
  a: 2,
  b: function() {
    return this.a;
  }
}
var t = obj.b;
console.log(t());//1

如上,t函數(shù)執(zhí)行結(jié)果竟然是全局變量1,為啥呢?這就涉及Javascript的內(nèi)存空間了,就是說,obj對(duì)象的b屬性存儲(chǔ)的是對(duì)該匿名函數(shù)的一個(gè)引用,可以理解為一個(gè)指針。當(dāng)賦值給t的時(shí)候,并沒有多帶帶開辟內(nèi)存空間存儲(chǔ)新的函數(shù),而是讓t存儲(chǔ)了一個(gè)指針,該指針指向這個(gè)函數(shù)。相當(dāng)于執(zhí)行了這么一段偽代碼:

var a = 1;
function fun() {//此函數(shù)存儲(chǔ)在堆中
    return this.a;
}
var obj = {
  a: 2,
  b: fun //b指向fun函數(shù)
}
var t = fun;//變量t指向fun函數(shù)
console.log(t());//1

此時(shí)的t就是一個(gè)指向fun函數(shù)的指針,調(diào)用t,相當(dāng)于直接調(diào)用fun,套用以上規(guī)則,打印出來1自然很好理解了。

使用apply,call

關(guān)于apply和call是干什么的怎么用本文不涉及,請(qǐng)移駕:apply,call

這是個(gè)萬能公式,實(shí)際上上面直接調(diào)用的代碼,我們可以看成這樣的:

function fun() {
      return this.a;
}
fun();//1
//嚴(yán)格模式
fun.call(undefined)
//非嚴(yán)格模式
fun.call(window)

這時(shí)候我們就可以解釋下,為啥說在非嚴(yán)格模式下,當(dāng)函數(shù)this指向undefined的時(shí)候,會(huì)自動(dòng)指向全局對(duì)象,如上,在非嚴(yán)格模式下,當(dāng)調(diào)用fun.call(undefined)的時(shí)候打印出來的依舊是1,就是最好的證據(jù)。

為啥說是萬能公式呢?再看函數(shù)作為對(duì)象的方法調(diào)用:

var a = 1;
var obj = {
  a: 2,
  b: function() {
    return this.a;
  }
}
obj.b()
obj.b.call(obj)

如上,是不是很強(qiáng)大,可以理解為其它兩種都是這個(gè)方法的語法糖罷了,那么apply和call是不是真的萬能的呢?并不是,ES6的箭頭函數(shù)就是特例,因?yàn)榧^函數(shù)的this不是在調(diào)用時(shí)候確定的,這也就是為啥說箭頭函數(shù)好用的原因之一,因?yàn)樗膖his固定不會(huì)變來變?nèi)サ牧?。關(guān)于箭頭函數(shù)的this我們稍后再說。

作為構(gòu)造函數(shù)

何為構(gòu)造函數(shù)?所謂構(gòu)造函數(shù)就是用來new對(duì)象的函數(shù),像FunctionObject、ArrayDate等都是全局定義的構(gòu)造函數(shù)。其實(shí)每一個(gè)函數(shù)都可以new對(duì)象,那些批量生產(chǎn)我們需要的對(duì)象的函數(shù)就叫它構(gòu)造函數(shù)罷了。注意,構(gòu)造函數(shù)首字母記得大寫。

function Fun() {
  this.name = "Damonre";
  this.age = 21;
  this.sex = "man";
  this.run = function () {
    return this.name + "正在跑步";
  }
}
Fun.prototype = {
  contructor: Fun,
  say: function () {
    return this.name + "正在說話";
  }
}
var f = new Fun();
f.run();//Damonare正在跑步
f.say();//Damonare正在說話

如上,如果函數(shù)作為構(gòu)造函數(shù)用,那么其中的this就代表它即將new出來的對(duì)象。為啥呢?new做了啥呢?

偽代碼如下:

function Fun() {
  //new做的事情
  var obj = {};
  obj.__proto__ = Fun.prototype;//Base為構(gòu)造函數(shù)
  obj.name = "Damonare";
  ...//一系列賦值以及更多的事
  return obj
}

也就是說new做了下面這些事:

創(chuàng)建一個(gè)臨時(shí)對(duì)象

給臨時(shí)對(duì)象綁定原型

給臨時(shí)對(duì)象對(duì)應(yīng)屬性賦值

將臨時(shí)對(duì)象return

也就是說new其實(shí)就是個(gè)語法糖,this之所以指向臨時(shí)對(duì)象還是沒逃脫上面說的幾種情況。

當(dāng)然如果直接調(diào)用Fun(),如下:

function Fun() {
  this.name = "Damonre";
  this.age = 21;
  this.sex = "man";
  this.run = function () {
    return this.name + "正在跑步";
  }
}
Fun();
console.log(window)

其實(shí)就是直接調(diào)用一個(gè)函數(shù),this在非嚴(yán)格模式下指向window,你可以在window對(duì)象找到所有的變量。

另外還有一點(diǎn),prototype對(duì)象的方法的this指向?qū)嵗龑?duì)象,因?yàn)閷?shí)例對(duì)象的__proto__已經(jīng)指向了原型函數(shù)的prototype。這就涉及原型鏈的知識(shí)了,即方法會(huì)沿著對(duì)象的原型鏈進(jìn)行查找。

箭頭函數(shù)

剛剛提到了箭頭函數(shù)是一個(gè)不可以用call和apply改變this的典型。

我們看下面這個(gè)?:

var a = 1;
var obj = {
  a: 2
};
var fun = () => console.log(this.a);
fun();//1
fun.call(obj)//1

以上,兩次調(diào)用都是1。

那么箭頭函數(shù)的this是怎么確定的呢?箭頭函數(shù)會(huì)捕獲其所在上下文的 this 值,作為自己的 this,也就是說箭頭函數(shù)的this在詞法層面就完成了綁定。apply,call方法只是傳入?yún)?shù),卻改不了this。

var a = 1;
var obj = {
  a: 2
};
function fun() {
    var a = 3;
    let f = () => console.log(this.a);
      f();
};
fun();//1
fun.call(obj);//2

如上,fun直接調(diào)用,fun的上下文中的this值為window,注意,這個(gè)地方有點(diǎn)繞。fun的上下文就是此箭頭函數(shù)所在的上下文,因此此時(shí)f的this為fun的this也就是window。當(dāng)fun.call(obj)再次調(diào)用的時(shí)候,新的上下文創(chuàng)建,fun此時(shí)的this為obj,也就是箭頭函數(shù)的this值。

再來一個(gè)?:

function Fun() {
    this.name = "Damonare";
}
Fun.prototype.say = () => {
    console.log(this);
}
var f = new Fun();
f.say();//window

有的同學(xué)看到這個(gè)?會(huì)很懵逼,感覺上this應(yīng)該指向f這個(gè)實(shí)例對(duì)象啊。不是的,此時(shí)的箭頭函數(shù)所在的上下文是__proto__所在的上下文也就是Object函數(shù)的上下文,而Object的this值就是全局對(duì)象。

那么再來一個(gè)?:

function Fun() {
    this.name = "Damonare";
      this.say = () => {
        console.log(this);
    }
}
var f = new Fun();
f.say();//Fun的實(shí)例對(duì)象

如上,this.say所在的上下文,此時(shí)箭頭函數(shù)所在的上下文就變成了Fun的上下文環(huán)境,而因?yàn)樯厦嬲f過當(dāng)函數(shù)作為構(gòu)造函數(shù)調(diào)用的時(shí)候(也就是new的作用)上下文環(huán)境的this指向?qū)嵗龑?duì)象。

后記

文中定義均為個(gè)人總結(jié),不妥之處還請(qǐng)雅正。

轉(zhuǎn)載請(qǐng)注明出處。

以上。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/84256.html

相關(guān)文章

  • JavaScript深入淺出

    摘要:理解的函數(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 的值到底...

    blair 評(píng)論0 收藏0
  • 學(xué)習(xí)React之前你需要知道的的JavaScript基礎(chǔ)知識(shí)

    摘要:和類在開始時(shí)遇到類組件,只是需要有關(guān)類的基礎(chǔ)。畢竟,中的條件呈現(xiàn)僅再次顯示大多數(shù)是而不是特定的任何內(nèi)容。 在我的研討會(huì)期間,更多的材料是關(guān)于JavaScript而不是React。其中大部分歸結(jié)為JavaScript ES6以及功能和語法,但也包括三元運(yùn)算符,語言中的簡寫版本,此對(duì)象,JavaScript內(nèi)置函數(shù)(map,reduce,filter)或更常識(shí)性的概念,如:可組合性,可重用...

    bitkylin 評(píng)論0 收藏0
  • JavaScript中的面向?qū)ο螅╫bject-oriented)編程

    摘要:對(duì)象在中,除了數(shù)字字符串布爾值這幾個(gè)簡單類型外,其他的都是對(duì)象。那么在函數(shù)對(duì)象中,這兩個(gè)屬性的有什么區(qū)別呢表示該函數(shù)對(duì)象的原型表示使用來執(zhí)行該函數(shù)時(shí)這種函數(shù)一般成為構(gòu)造函數(shù),后面會(huì)講解,新創(chuàng)建的對(duì)象的原型。這時(shí)的函數(shù)通常稱為構(gòu)造函數(shù)。。 本文原發(fā)于我的個(gè)人博客,經(jīng)多次修改后發(fā)到sf上。本文仍在不斷修改中,最新版請(qǐng)?jiān)L問個(gè)人博客。 最近工作一直在用nodejs做開發(fā),有了nodejs,...

    JerryZou 評(píng)論0 收藏0
  • JavaScript進(jìn)階之’this

    摘要:所以相同點(diǎn)是,在全局范圍內(nèi),全局變量終究是屬于老大的。只生效一次引入了。只生效一次在箭頭函數(shù)中,與封閉詞法環(huán)境的保持一致。我通常把這些原始函數(shù)叫做構(gòu)造函數(shù)。在里面你可以嵌套函數(shù),也就是你可以在函數(shù)里面定義函數(shù)。 showImg(https://img-blog.csdnimg.cn/20190522000008399.jpg?x-oss-process=image/watermark,...

    shenhualong 評(píng)論0 收藏0
  • 理解 JavaScript 中的 this 關(guān)鍵字

    摘要:原文許多人被中的關(guān)鍵字給困擾住了,我想混亂的根源來自人們理所當(dāng)然地認(rèn)為中的應(yīng)該像中的或中的一樣工作。盡管有點(diǎn)難理解,但它的原理并不神秘。在瀏覽器中,全局對(duì)象是對(duì)象。運(yùn)算符創(chuàng)建一個(gè)新對(duì)象并且設(shè)置函數(shù)中的指向調(diào)用函數(shù)的新對(duì)象。 原文:Understanding the this keyword in JavaScript 許多人被JavaScript中的this關(guān)鍵字給困擾住了,我想混亂的...

    jayzou 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

SimpleTriangle

|高級(jí)講師

TA的文章

閱讀更多
最新活動(dòng)
閱讀需要支付1元查看
<