成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

JavaScript中的this

Salamander / 1100人閱讀

摘要:指向的改變構(gòu)造函數(shù)中的操作符會(huì)調(diào)用函數(shù)的內(nèi)部的方法,創(chuàng)建對(duì)象,之后調(diào)用函數(shù)的方法,把新創(chuàng)建對(duì)象作為值。調(diào)用函數(shù)時(shí)與設(shè)置的值以及箭頭函數(shù)皆為動(dòng)態(tài)的改變指針的方法。這一特性使得箭頭函數(shù)在中的函數(shù)中使用起來(lái)很方便。

原文地址

JavaScript中的this 原理 錯(cuò)誤的this指向

通常所說(shuō)的:如果是全局環(huán)境中,this指向全局對(duì)象,如果是對(duì)象的方法,這this指向這個(gè)對(duì)象。

例子1:

var foo = {
  bar: function() {
    console.log(this)
  }
}

foo.bar();
(foo.bar)();

(foo.bar = foo.bar)();
(false || foo.bar)();
(foo.bar, foo.bar)();

例子1前兩者為foo,后面都是全局對(duì)象。后三者并沒(méi)有指向foo。所以我們上面的通常說(shuō)法不精確。

精確的this指向

在全局環(huán)境中,this指向全局對(duì)象。而在普通函數(shù)調(diào)用中,this是由激活上下文的調(diào)用者提供,即調(diào)用這個(gè)函數(shù)的父作用域,以及函數(shù)調(diào)用的語(yǔ)法形式,決定了this的值,這是一個(gè)動(dòng)態(tài)可變的值。

例子2:

var foo = {
  bar: function() {
    console.log(this)
    console.log(this === foo)
  }
}

foo.bar() // foo, true

var fn = foo.bar

console.log(fn === foo.bar) // true

fn() // global, false

例子2中,第一次調(diào)用指向foo,把foo.bar賦值給fn之后,this沒(méi)有指向foo。是什么導(dǎo)致this指向的變化呢?

this指向的內(nèi)部原理

this是執(zhí)行上下文的一個(gè)屬性:

activeExecutionContext = {
  VO: {...},
  this: thisValue
}

在普通函數(shù)調(diào)用中,this是由激活上下文的調(diào)用者提供,即調(diào)用這個(gè)函數(shù)的父作用域,函數(shù)調(diào)用的語(yǔ)法形式,決定了this的值,這是一個(gè)動(dòng)態(tài)可變的值。

為什么會(huì)引起這個(gè)差異呢?
因?yàn)橐妙愋偷牟煌幚?,是否?huì)獲取真實(shí)的值,所導(dǎo)致的。

引用類型存在形式:

1 標(biāo)識(shí)符(變量名,函數(shù)名,函數(shù)參數(shù)名,全局對(duì)象屬性名)

2 屬性訪問(wèn)器(foo.bar(); foo["bar"](), 點(diǎn)標(biāo)記法;可以動(dòng)態(tài)設(shè)置屬性名的方括號(hào)[]

為了從引用類型中獲取真實(shí)的值,存在類似getValue的方法。而函數(shù)上下文的規(guī)則是,函數(shù)上下文中this由調(diào)用者提供,并由調(diào)用形式?jīng)Q定。如果調(diào)用的圓括號(hào)左側(cè)是一個(gè)引用類型,this為這個(gè)引用類型,如果是非引用類型,這為null,但為null無(wú)意義,被隱式轉(zhuǎn)化為全局對(duì)象。

為什么有this的特性?

this是一個(gè)指針,便于代碼的更為簡(jiǎn)潔地復(fù)用。

// 無(wú)this
function upper(context) {
  return context.name.toUpperCase()
}
function speak(context) {
  var greeting = "Hello, I"m " + upper(context)
  console.log(greeting)
}

var me = {
  name: "m"
}

var you = {
  name: "y"
}

speak(me)

// 利用this

function upper() {
  return this.name.toUpperCase()
}
function speak() {
  var greeting = "Hello, I"m " + upper.call(this)
  console.log(greeting)
}

speak.call(me)

這里this可以簡(jiǎn)化上下文對(duì)象的傳遞。其他OPP語(yǔ)言中this關(guān)鍵字和OPP密切相關(guān),一般是引用剛創(chuàng)建的對(duì)象,但在ECMAScript中,this只限于引用創(chuàng)建過(guò)的對(duì)象,this的指向和函數(shù)調(diào)用形式有關(guān),不一定引用類型調(diào)用就指向引用類型。

this指向的改變

1 構(gòu)造函數(shù)中的this

function C() {
  console.log(this)
  this.x = 10
}

var a = new C()
console.log(a.x);

new操作符會(huì)調(diào)用函數(shù)的內(nèi)部的Construct方法,創(chuàng)建對(duì)象,之后調(diào)用函數(shù)的Call方法,把新創(chuàng)建對(duì)象作為this值。

2 調(diào)用函數(shù)時(shí)call與apply設(shè)置this的值

var b = 10
function a(c) {
  console.log(this.b)
  console.log(c)
}

a(20)
a.call({b: 20}, 30)
a.apply({b: 20}, [40])
call, apply, bind以及箭頭函數(shù)

call,apply,bind皆為動(dòng)態(tài)的改變this指針的方法。其中call和apply是當(dāng)Object沒(méi)有某個(gè)方法,但是其它對(duì)象有,可以借助call和apply改變this的指向,調(diào)用其它對(duì)象的方法。bind為綁定this為某個(gè)對(duì)象。

典型的應(yīng)用:

將類數(shù)組元素轉(zhuǎn)化為數(shù)組:
Array.prototype.slice.apply(document.getElementsByTagName("*"))

檢查類型:

function isArray(obj) {
  return Object.prototpye.toString.call(obj) === "[object Array]"
}

箭頭函數(shù)則與前三者不同。
If kind is Arrow, set the [[ThisModel]] internal slot of F to lexical.If the
value is "lexical", this is an ArrowFunction and does not have a local this

If thisModel is lexical, return NormalCompletion(undefined).

箭頭函數(shù)沒(méi)有自己的this綁定,同時(shí)在函數(shù)執(zhí)行時(shí)綁定this會(huì)被直接忽略。其中this總是指向定義時(shí)所在的對(duì)象,而不是運(yùn)行時(shí)所在的對(duì)象。即箭頭函數(shù)的this值是lexical
scope 的this值。這一特性使得箭頭函數(shù)在React中的render函數(shù)中使用起來(lái)很方便。

function foo() {
  setTimeout(() => {
    console.log("id: ", this.id)
  }, 100)
}

var id = 0

foo.call({id: 42})

// 容易誤解的地方
// {id: 42}
// 是箭頭函數(shù)定義所在的對(duì)象還是運(yùn)行時(shí)所在的對(duì)象。由于箭頭函數(shù)位于foo函數(shù)內(nèi)部,只有foo函數(shù)運(yùn)行之后他才會(huì)生成,所以foo運(yùn)行時(shí)所在的對(duì)象,即箭頭函數(shù)定義所在的對(duì)象。
var f = () => 5;
// 近似等價(jià)于
var f = function() {return 5;}.bind(this);

綜上,call,apply,bind使得JavaScript具有動(dòng)態(tài)改變this的特性,而箭頭函數(shù)使得JavaScript具有固定this的指向的特性。一動(dòng)一靜,相得益彰。

在編程中的運(yùn)用 ES7中的::
  this.x = 0
  let module = {
    x: 1,
    getX: function() {
      console.log(this.x)
    }
  }
  module.getX()
  let get = module.getX
  get() // 0
  let boundGetX = get.bind(module)
  boundGetX() // 1
  let ES7boundGetx = module::get
  ES7boundGetx() // 1
super
class P {
  foo() {
    console.log("P.foo")
  }
}

class C extends P {
  foo() {
    super.foo()
  }
}

var c1 = new C()
c1.foo() // P.foo

var D = {
  foo: function() {
    console.log("D.foo")
  }
}

var E = {
  foo: C.prototype.foo
}

Object.setPrototypeOf(E, D)
E.foo() // P.foo

可見(jiàn)super的綁定是靜態(tài)綁定,創(chuàng)建時(shí)即完成綁定。所以E委托了D,但并不能調(diào)用到D.foo(),類似于箭頭的函數(shù)的this綁定。

jQuery中的this

鏈?zhǔn)秸{(diào)用的實(shí)現(xiàn);

function Constructor() {
  this.art = 0
}

Constructor.prototype.fn_0 = function() {
  console.log("0")
  return this;
}

Constructor.prototype.fn_1 = function() {
  console.log("1")
  return this;
}

new Constructor().fn_0().fn_1()

調(diào)用的方法返回this即可。

end()的實(shí)現(xiàn)

function end() {
  return this.prevObject || this.constructor(null)
}

// 設(shè)置preObject的函數(shù)
function pushStack( ele ) {
  // Build a new jQuery macthed element set
  var ret = jQuery.merge( this.constructor(), elems);
  ret.prevObject = this // ret.pervObject 設(shè)置為當(dāng)前jQuery對(duì)象引用
  ret.context = this.context
  return ret;
}

pushStack函數(shù)在很多涉及DOM操作的函數(shù)都有調(diào)用,用于緩存了當(dāng)前的this。由于只存儲(chǔ)當(dāng)前,所以這里只需要一個(gè)preObject即可,無(wú)需放在一個(gè)數(shù)組里。

利與弊

this是JavaScript特性之一,具有腳本語(yǔ)言的動(dòng)態(tài)特性,帶來(lái)很多便捷,同時(shí)由于super和箭頭函數(shù)的特性,使得this具有了靜態(tài)的特性,在這兩種情況下,this是固定且無(wú)法改變的。其利與弊都是this的靈活,雙刃劍。所以才有了ES2015中super和箭頭函數(shù)的固定this的特性。

拾遺

this可被重新賦值么?(不能,this是保留字)

問(wèn)題(答案見(jiàn)原文)

1 call參數(shù)為null時(shí),this的指向

function a() {
  console.log(this)
}
a.call(null)

2 調(diào)用形式對(duì)this的影響

var foo = {
  bar: function() {
    console.log(this)
  }
}

foo.bar();
(foo.bar)();

(foo.bar = foo.bar)();
(false || foo.bar)();
(foo.bar, foo.bar)();
參考資料:

《你所不知道的JavaScript(上卷)》

關(guān)于JavaScript的執(zhí)行域,標(biāo)識(shí)符解析,閉包的研究

深入ECMA-262-3 第三章、This

JavaScript內(nèi)部原理實(shí)踐——真的懂JavaScript嗎?

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

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/81479.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ī)?lái)幫助....(據(jù)說(shuō)是阿里的前端妹子寫的) 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ǔ)法,但也包括三元運(yùn)算符,語(yǔ)言中的簡(jiǎn)寫版本,此對(duì)象,JavaScript內(nèi)置函數(shù)(map,reduce,filter)或更常識(shí)性的概念,如:可組合性,可重用...

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

    摘要:對(duì)象在中,除了數(shù)字字符串布爾值這幾個(gè)簡(jiǎn)單類型外,其他的都是對(duì)象。那么在函數(shù)對(duì)象中,這兩個(gè)屬性的有什么區(qū)別呢表示該函數(shù)對(duì)象的原型表示使用來(lái)執(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問(wèn)個(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)鍵字給困擾住了,我想混亂的根源來(lái)自人們理所當(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)論

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