亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

JavaScript中的this

Salamander / 1131人閱讀

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

原文地址

JavaScript中的this 原理 錯誤的this指向

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

例子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,后面都是全局對象。后三者并沒有指向foo。所以我們上面的通常說法不精確。

精確的this指向

在全局環(huán)境中,this指向全局對象。而在普通函數(shù)調(diào)用中,this是由激活上下文的調(diào)用者提供,即調(diào)用這個函數(shù)的父作用域,以及函數(shù)調(diào)用的語法形式,決定了this的值,這是一個動態(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沒有指向foo。是什么導(dǎo)致this指向的變化呢?

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

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

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

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

為什么會引起這個差異呢?
因為引用類型的不同處理,是否會獲取真實的值,所導(dǎo)致的。

引用類型存在形式:

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

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

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

為什么有this的特性?

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

// 無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可以簡化上下文對象的傳遞。其他OPP語言中this關(guān)鍵字和OPP密切相關(guān),一般是引用剛創(chuàng)建的對象,但在ECMAScript中,this只限于引用創(chuàng)建過的對象,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操作符會調(diào)用函數(shù)的內(nèi)部的Construct方法,創(chuàng)建對象,之后調(diào)用函數(shù)的Call方法,把新創(chuàng)建對象作為this值。

2 調(diào)用函數(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皆為動態(tài)的改變this指針的方法。其中call和apply是當(dāng)Object沒有某個方法,但是其它對象有,可以借助call和apply改變this的指向,調(diào)用其它對象的方法。bind為綁定this為某個對象。

典型的應(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ù)沒有自己的this綁定,同時在函數(shù)執(zhí)行時綁定this會被直接忽略。其中this總是指向定義時所在的對象,而不是運行時所在的對象。即箭頭函數(shù)的this值是lexical
scope 的this值。這一特性使得箭頭函數(shù)在React中的render函數(shù)中使用起來很方便。

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

var id = 0

foo.call({id: 42})

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

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

在編程中的運用 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

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

jQuery中的this

鏈?zhǔn)秸{(diào)用的實現(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()的實現(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對象引用
  ret.context = this.context
  return ret;
}

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

利與弊

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

拾遺

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

問題(答案見原文)

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

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

2 調(diào)用形式對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)識符解析,閉包的研究

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

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

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

轉(zhuǎn)載請注明本文地址:http://www.ezyhdfw.cn/yun/81479.html

相關(guān)文章

  • JavaScript深入淺出

    摘要:理解的函數(shù)基礎(chǔ)要搞好深入淺出原型使用原型模型,雖然這經(jīng)常被當(dāng)作缺點提及,但是只要善于運用,其實基于原型的繼承模型比傳統(tǒng)的類繼承還要強大。中文指南基本操作指南二繼續(xù)熟悉的幾對方法,包括,,。商業(yè)轉(zhuǎn)載請聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請注明出處。 怎樣使用 this 因為本人屬于偽前端,因此文中只看懂了 8 成左右,希望能夠給大家?guī)韼椭?...(據(jù)說是阿里的前端妹子寫的) this 的值到底...

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

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

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

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

    JerryZou 評論0 收藏0
  • JavaScript進階之’this

    摘要:所以相同點是,在全局范圍內(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 評論0 收藏0
  • 理解 JavaScript 中的 this 關(guān)鍵字

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

    jayzou 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<