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

資訊專欄INFORMATION COLUMN

前端之ECMAScript 實(shí)戰(zhàn):this的用法

kun_jian / 1334人閱讀

摘要:在等面向?qū)ο蟮恼Z言中,關(guān)鍵字的含義是明確且具體的,即指代當(dāng)前對(duì)象。一般在編譯期確定下來,或稱為編譯期綁定。無論是用還是這種方式,都取決于傳入該函數(shù)的對(duì)象。使用方法綁定使用在創(chuàng)建時(shí)綁定指針。如果是行內(nèi)的事件監(jiān)聽者,指針會(huì)被設(shè)置為其所在的元素

this

在 Java 等面向?qū)ο蟮恼Z言中,this 關(guān)鍵字的含義是明確且具體的,即指代當(dāng)前對(duì)象。一般在編譯期確定下來,或稱為編譯期綁定。而在 JavaScript 中,this 是動(dòng)態(tài)綁定,或稱為運(yùn)行期綁定的,這就導(dǎo)致 JavaScript 中的 this 關(guān)鍵字有能力具備多重含義,變得有點(diǎn)隨意。而在ES6中又引入了Arrow Function以及Class,它們對(duì)于this指針也帶來了一定的影響。

Global Context(全局上下文)

在任何函數(shù)之外的全局環(huán)境中,不管在不在strict模式中,this指針往往指向一個(gè)全局變量。

console.log(this.document === document); // true

// In web browsers, the window object is also the global object:
console.log(this === window); // true

this.a = 37;
console.log(window.a); // 37
Function Context(函數(shù)上下文) 簡(jiǎn)單調(diào)用

在某個(gè)函數(shù)中,this的值取決于該函數(shù)的調(diào)用者。無論是用hello("world”)還是call這種方式,都取決于傳入該函數(shù)的對(duì)象。不過,在ES5的嚴(yán)格或者不嚴(yán)格模式下,同樣的調(diào)用方式會(huì)有不同的結(jié)果。

function hello(thing) {  
  console.log("Hello " + thing);
}

// this:
hello("world")

// desugars to:
hello.call(window, "world");  

而如果是strict模式下:

// this:
hello("world")

// desugars to:
hello.call(undefined, "world");  
對(duì)象方法

另一種常用的調(diào)用函數(shù)的方法就是在object中調(diào)用:

function hello(thing) {  
  console.log(this + " says hello " + thing);
}

person = { name: "Brendan Eich" }  
person.hello = hello;

person.hello("world") // still desugars to person.hello.call(person, "world") [object Object] says hello world

hello("world") // "[object DOMWindow]world"  
bind

很多時(shí)候,需要為某個(gè)函數(shù)指定一個(gè)固定的this對(duì)象,最簡(jiǎn)單的方式即是使用閉包來獲取一個(gè)不變的this對(duì)象。

var person = {  
  name: "Brendan Eich",
  hello: function(thing) {
    console.log(this.name + " says hello " + thing);
  }
}

var boundHello = function(thing) { return person.hello.call(person, thing); }

boundHello("world");  

不過,這種方式仍然存在著一定的問題,ES5為Function對(duì)象引入了一個(gè)新的bind方法來解決這個(gè)問題:

var boundHello = person.hello.bind(person);  
boundHello("world") // "Brendan Eich says hello world"  

這種方式在設(shè)置回調(diào)函數(shù)中的this指針的時(shí)候會(huì)起到很大的作用,特別是在React中,為了保證指針的穩(wěn)定性,往往需要為內(nèi)置方法設(shè)置bind。

var person = {  
  name: "Alex Russell",
  hello: function() { console.log(this.name + " says hello world"); }
}

$("#some-div").click(person.hello.bind(person));

// when the div is clicked, "Alex Russell says hello world" is printed
apply/call

在 JavaScript 中函數(shù)也是對(duì)象,對(duì)象則有方法,apply 和 call 就是函數(shù)對(duì)象的方法。這兩個(gè)方法異常強(qiáng)大,他們?cè)试S切換函數(shù)執(zhí)行的上下文環(huán)境(context),即 this 綁定的對(duì)象。很多 JavaScript 中的技巧以及類庫都用到了該方法。讓我們看一個(gè)具體的例子:

function Point(x, y){ 
    this.x = x; 
    this.y = y; 
    this.moveTo = function(x, y){ 
        this.x = x; 
        this.y = y; 
    } 
 } 

 var p1 = new Point(0, 0); 
 var p2 = {x: 0, y: 0}; 
 p1.moveTo(1, 1); 
 p1.moveTo.apply(p2, [10, 10]);
array.forEach

在這樣一個(gè)回調(diào)函數(shù)中,回調(diào)函數(shù)的this指針是由調(diào)用者決定的,完整的forEach聲明如下:array.forEach(callback[, thisArg]),這個(gè)傳入的thisArg即是回調(diào)的調(diào)用者。

var o={
   v:"hello",
   p:["a1","a2"],
   f:function f(){
      this.p.forEach(function (item){
           console.log(this.v+" "+item);
      });
   }
}

o.f();
//undefined a1
//undefined a2
Arrow Function

Arrow Function是ES6新增的特性,很類似于Java或者C#中的Lambda表達(dá)式。Arrow函數(shù)中的this指針在創(chuàng)建時(shí)就被綁定到了閉合的作用域內(nèi),不會(huì)收到new、bind、call以及apply這些方法的影響。

var o = {
  traditionalFunc: function () {
    // Normal function, bound as expected
    console.log("traditionalFunc this === o?", this === o);
  },
  arrowFunc: () => {
    // Arrow function, bound to scope where it"s created
    console.log("arrowFunc this === o?", this === o);
    console.log("arrowFunc this === window?", this === window);
  }
};

o.traditionalFunc();
// traditionalFunc this === o? true

o.arrowFunc();
// arrowFunc this === o? false
// arrowFunc this === window? true

上述代碼中的arrowFunc隸屬于o對(duì)象,但是在window的作用域中被創(chuàng)建,因此,最終arrow函數(shù)中的this指針的值等于window對(duì)象。ES5中的對(duì)于this的控制已然非常復(fù)雜,特別是在處理異步代碼中如何傳入合適的this對(duì)象也是一件麻煩事,如下文所示:

var asyncFunction = (param, callback) => {
  window.setTimeout(() => {
    callback(param);
  }, 1);
};

// With a traditional function if we don"t control 
// the context then can we lose control of `this`.
var o = {
  doSomething: function () {
    // Here we pass `o` into the async function, 
    // expecting it back as `param`
    asyncFunction(o, function (param) {
      // We made a mistake of thinking `this` is 
      // the instance of `o`.
      console.log("param === this?", param === this);
    });
  }
};

o.doSomething(); // param === this? false

為了綁定上述代碼中的this指針,一般來說有三個(gè)辦法:

為this指針創(chuàng)建一個(gè)固定的引用。

var asyncFunction = (param, callback) => {
  window.setTimeout(() => {
    callback(param);
  }, 1);
};

// Define a reference to `this` outside of the callback, 
// but within the callback"s lexical scope
var o = {
  doSomething: function () {
    var self = this;
    // Here we pass `o` into the async function, 
    // expecting it back as `param`
    asyncFunction(o, function (param) {
      console.log("param === this?", param === self);
    });
  }
};

o.doSomething(); // param === this? true

使用bind方法綁定this

var asyncFunction = (param, callback) => {
  window.setTimeout(() => {
    callback(param);
  }, 1);
};

// Here we control the context of the callback using
// `bind` ensuring `this` is correct
var o = {
  doSomething: function () {
    // Here we pass `o` into the async function, 
    // expecting it back as `param`
    asyncFunction(o, function (param) {
      console.log("param === this?", param === this);
    }.bind(this));
  }
};

o.doSomething(); // param === this? true

使用Arrow Function在創(chuàng)建時(shí)綁定this指針。

var asyncFunction = (param, callback) => {
  window.setTimeout(() => {
    callback(param);
  }, 1);
};

var o = {
  doSomething: function () {
    // Here we pass `o` into the async function, 
    // expecting it back as `param`. 
    //
    // Because this arrow function is created within  
    // the scope of `doSomething` it is bound to this 
    // lexical scope.
    asyncFunction(o, (param) => {
      console.log("param === this?", param === this);
    });
  }
};

o.doSomething(); // param === this? true
DOM Event handler(Dom事件)

當(dāng)某個(gè)函數(shù)作為事件監(jiān)聽器時(shí),它的this值往往被設(shè)置為它的調(diào)用者。

// When called as a listener, turns the related element blue
function bluify(e){
  // Always true
  console.log(this === e.currentTarget); 
  // true when currentTarget and target are the same object
  console.log(this === e.target);
  this.style.backgroundColor = "#A5D9F3";
}

// Get a list of every element in the document
var elements = document.getElementsByTagName("*");

// Add bluify as a click listener so when the
// element is clicked on, it turns blue
for(var i=0 ; i

如果是行內(nèi)的事件監(jiān)聽者,this指針會(huì)被設(shè)置為其所在的DOM元素:

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

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/86029.html

相關(guān)文章

  • ECMASCRIPT 6 實(shí)戰(zhàn) 擴(kuò)展運(yùn)算符

    摘要:擴(kuò)展運(yùn)算符是以下簡(jiǎn)稱中又一非常好用的實(shí)戰(zhàn)技術(shù)它的寫法只需要三個(gè)點(diǎn)作用則顧名思義用來展開你想要使用的任意變量本質(zhì)上是對(duì)所有擁有迭代器接口的對(duì)象進(jìn)行迭代。 擴(kuò)展運(yùn)算符(spreading)是 ECMASCRIPT 6(以下簡(jiǎn)稱ES 6) 中又一非常好用的實(shí)戰(zhàn)技術(shù), 它的寫法只需要三個(gè)點(diǎn)(...),作用則顧名思義,用來展開你想要使用的任意變量,本質(zhì)上是對(duì)所有擁有迭代器接口(Iterator)...

    habren 評(píng)論0 收藏0
  • ECMASCRIPT 6 實(shí)戰(zhàn) 解構(gòu)賦值

    摘要:相信解構(gòu)賦值自以下簡(jiǎn)稱面世以來被大家快速地熟悉并運(yùn)用到實(shí)際開發(fā)中了這是一種能有效減少代碼量,使代碼邏輯更簡(jiǎn)單優(yōu)雅的技術(shù)下面我們就再來回顧總結(jié)一下解構(gòu)賦值的種種用法吧基本用法從對(duì)象解構(gòu)假設(shè)有一個(gè)對(duì)象,它的結(jié)構(gòu)為以對(duì)稱的形式從從邊的對(duì)象中匹配與 相信解構(gòu)賦值(Destructuring)自 ECMASCRIPT 6(以下簡(jiǎn)稱 ES 6) 面世以來被大家快速地熟悉并運(yùn)用到實(shí)際開發(fā)中了, 這是...

    yangrd 評(píng)論0 收藏0
  • 前端培訓(xùn)-初級(jí)階段(13) - 正則表達(dá)式

    摘要:前端培訓(xùn)初級(jí)階段語法變量值類型運(yùn)算符語句前端培訓(xùn)初級(jí)階段內(nèi)置對(duì)象函數(shù)前端培訓(xùn)初級(jí)階段類模塊繼承基礎(chǔ)內(nèi)容知識(shí)我們會(huì)用到。 前端最基礎(chǔ)的就是 HTML+CSS+Javascript。掌握了這三門技術(shù)就算入門,但也僅僅是入門,現(xiàn)在前端開發(fā)的定義已經(jīng)遠(yuǎn)遠(yuǎn)不止這些。前端小課堂(HTML/CSS/JS),本著提升技術(shù)水平,打牢基礎(chǔ)知識(shí)的中心思想,我們開課啦(每周四)。 該文為前端培訓(xùn)-初級(jí)階段(1...

    suemi 評(píng)論0 收藏0
  • 根治JavaScript中this-ECMAScript規(guī)范解讀

    摘要:執(zhí)行函數(shù)調(diào)用規(guī)范中的第一步是一個(gè)明顯的賦值語句,我們查看規(guī)范,賦值語句會(huì)發(fā)生什么可以看出簡(jiǎn)單賦值語句返回的是對(duì)等于號(hào)右邊進(jìn)行之后的結(jié)果,上一節(jié)講了,執(zhí)行過就會(huì)返回的類型,此處會(huì)返回也就是一個(gè)類型。 前言 this是JavaScript中的著名月經(jīng)題,每隔一段時(shí)間就有人翻出了拿各種奇怪的問題出來討論,每次都會(huì)引發(fā)一堆口水之爭(zhēng)。從搜索引擎搜了一下現(xiàn)在的比較熱門的關(guān)于this的用法,如:Ja...

    notebin 評(píng)論0 收藏0
  • JavaScript - 收藏集 - 掘金

    摘要:插件開發(fā)前端掘金作者原文地址譯者插件是為應(yīng)用添加全局功能的一種強(qiáng)大而且簡(jiǎn)單的方式。提供了與使用掌控異步前端掘金教你使用在行代碼內(nèi)優(yōu)雅的實(shí)現(xiàn)文件分片斷點(diǎn)續(xù)傳。 Vue.js 插件開發(fā) - 前端 - 掘金作者:Joshua Bemenderfer原文地址: creating-custom-plugins譯者:jeneser Vue.js插件是為應(yīng)用添加全局功能的一種強(qiáng)大而且簡(jiǎn)單的方式。插....

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

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

0條評(píng)論

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