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

資訊專欄INFORMATION COLUMN

this的指向(附面試題)

blair / 1079人閱讀

摘要:是的幾乎是全部。語法和區(qū)別在里面的指向的不是事件的調(diào)用者,而是奇葩,而指向的事件調(diào)用者。舉例來說使用作為來調(diào)用面試題四明確綁定的優(yōu)先權(quán)要高于隱含綁定綁定的優(yōu)先級(jí)高于隱含綁定和不能同時(shí)使用,所以是不允許的,也就是不能直接對(duì)比測(cè)試綁定和明確綁定

ES5中this的指針

按照this指針的優(yōu)先級(jí),列出下面常會(huì)遇到的四種情況,從上到下依次是優(yōu)先級(jí)從高到低(后面會(huì)詳細(xì)比較優(yōu)先級(jí))。

函數(shù)是和new一起被調(diào)用的嗎(new綁定)?如果是,this就是新構(gòu)建的對(duì)象。

var bar = new foo()

函數(shù)是用callapply被調(diào)用(明確綁定),甚至是隱藏在bind 硬綁定 之中嗎?如果是,this就是明確指定的對(duì)象。

var bar = foo.call( obj2 )

函數(shù)是用環(huán)境對(duì)象(也稱為擁有者或容器對(duì)象)被調(diào)用的嗎(隱含綁定)?如果是,this就是那個(gè)環(huán)境對(duì)象。

var bar = obj1.foo()

否則,使用默認(rèn)的this默認(rèn)綁定)。如果在strict mode下,就是undefined,否則是global對(duì)象。 var bar = foo()

以上,就是理解對(duì)于普通的函數(shù)調(diào)用來說的this綁定規(guī)則所需的全部。是的···幾乎是全部。

apply、call、bind

因?yàn)閍pply、call存在于Function.prototype中,所以每個(gè)方法都有這兩個(gè)屬性。

call

函數(shù)名.call(對(duì)象,arg1....argn)
//功能:
    //1.調(diào)用函數(shù)
    //2.將函數(shù)內(nèi)部的this指向第一個(gè)參數(shù)的對(duì)象
    //3.將第二個(gè)及以后所有的參數(shù),作為實(shí)參傳遞給函數(shù)

apply
主要用途是直接用數(shù)組傳參

函數(shù)名.apply(對(duì)象, 數(shù)組/偽數(shù)組);
//功能:
    //1.調(diào)用函數(shù)
    //2.將函數(shù)內(nèi)部的this指向第一個(gè)參數(shù)的對(duì)象
    //3.將第二個(gè)參數(shù)中的數(shù)組(偽數(shù)組)中的元素,拆解開依次的傳遞給函數(shù)作為實(shí)參
//案例求數(shù)組中最大值
var a=Math.max.apply( null, [ 1, 2, 5, 3, 4 ] );
console.log(a);// 輸出:5

bind

是創(chuàng)建一個(gè)新的函數(shù),我們必須要手動(dòng)去調(diào)用:

var a ={
  name : "Cherry",
  fn : function (a,b) {
   console.log( a + b)
  }
 }
 var b = a.fn;
 b.bind(a,1,2)()   // 3

注意事項(xiàng)

call和apply功能幾乎一致,唯一的區(qū)別就是傳參的方式??!
2.call和apply的第一個(gè)參數(shù)如果為null或者undefined,那么this指向window
3.call和apply的第一個(gè)參數(shù)如果為值類型的數(shù)據(jù),那么會(huì)將這個(gè)值類型的數(shù)據(jù),轉(zhuǎn)換成其對(duì)應(yīng)的引用類型的數(shù)據(jù),然后再將this指向這個(gè)引用類型的數(shù)據(jù)
4.call和apply立即執(zhí)行這個(gè)函數(shù),bind方法可以讓對(duì)應(yīng)的函數(shù)想什么時(shí)候調(diào)就什么時(shí)候調(diào)用,并且可以將參數(shù)在執(zhí)行的時(shí)候添加,這是它們的區(qū)別,根據(jù)自己的實(shí)際情況來選擇使用。
5.當(dāng)參數(shù)的個(gè)數(shù)確定的情況下可以使用call;當(dāng)參數(shù)的個(gè)數(shù)不確定的情況下可以使用apply

apply應(yīng)用
JavaScript

var array1 = [12 , "foo" , {name "Joe"} , -2458]; 
var array2 = ["Doe" , 555 , 100]; 
Array.prototype.push.apply(array1, array2); 
/* array1 值為  [12 , "foo" , {name "Joe"} , -2458 , "Doe" , 555 , 100] */
call應(yīng)用(將偽數(shù)組轉(zhuǎn)為數(shù)組)
var arrayLike = {0: "name", 1: "age", 2: "sex", length: 3 }
Array.prototype.join.call(arrayLike, "&"); // name&age&sex
Array.prototype.slice.call(arrayLike, 0); // ["name", "age", "sex"] 
// slice可以做到類數(shù)組轉(zhuǎn)數(shù)組
Array.prototype.map.call(arrayLike, function(item){
    return item.toUpperCase();
}); 
// ["NAME", "AGE", "SEX"]
call應(yīng)用(判斷復(fù)雜數(shù)據(jù)類型)
console.log(
    Object.prototype.toString.call(num),
    Object.prototype.toString.call(str),
    Object.prototype.toString.call(bool),
    Object.prototype.toString.call(arr),
    Object.prototype.toString.call(json),
    Object.prototype.toString.call(func),
    Object.prototype.toString.call(und),
    Object.prototype.toString.call(nul),
    Object.prototype.toString.call(date),
    Object.prototype.toString.call(reg),
    Object.prototype.toString.call(error)
);
// "[object Number]" "[object String]" "[object Boolean]" "[object Array]" "[object Object]"
// "[object Function]" "[object Undefined]" "[object Null]" "[object Date]" "[object RegExp]" "[object Error]"
bind在react中應(yīng)用

下面的例子是來自react官網(wǎng)的案例

class Toggle extends React.Component {
  constructor(props) {
    super(props);
    this.state = {isToggleOn: true};

    // This binding is necessary to make `this` work in the callback
    this.handleClick = this.handleClick.bind(this);
  }

  handleClick() {
    console.log(this);
    this.setState(prevState => ({
      isToggleOn: !prevState.isToggleOn
    }));
  }

  render() {
    return (
      
    );
  }
}

ReactDOM.render(
  ,
  document.getElementById("root")
);

If you forget to bind this.handleClick and pass it to onClick, this will be undefined when the function is actually called.

ES6中this的指向 箭頭函數(shù)this指向注意事項(xiàng)

箭頭函數(shù)體內(nèi)的this對(duì)象,如果包裹在函數(shù)中就是函數(shù)調(diào)用時(shí)所在的對(duì)象,如果放在全局中就是指全局對(duì)象window。并且固定不會(huì)更改。換句話說內(nèi)部的this就是外層代碼塊的this

下面是對(duì)比分析普通函數(shù)和箭頭函數(shù)中this區(qū)別

// 普通函數(shù)
function foo() {
  setTimeout(function() {
    console.log("id:", this.id);
  });
}

var id = 21;
foo.call({ id: 42 }); //21
// 箭頭函數(shù)
function foo() {
  setTimeout(() => {
    console.log("id:", this.id);
  }, 100);
}

var id = 21;
foo.call({ id: 42 }); //42
// 上面的匿名函數(shù)定義時(shí)所在的執(zhí)行環(huán)境就是foo函數(shù),所以匿名函數(shù)內(nèi)部的this執(zhí)向始終會(huì)和foo函數(shù)的this執(zhí)向保持一致,不會(huì)更改,如同下面的這個(gè)案例
function foo() {
  setTimeout(() => {
    console.log("id:", this.id);
  }, 100);
}

var id = 21;
foo(); //21(沒有用call)
// ES5普通函數(shù)模擬上面es6函數(shù)的執(zhí)行過程
function foo() {
  var _this = this;

  setTimeout(function () {
    console.log("id:", _this.id);
  }, 100);
}

call的作用就是將foo函數(shù)的執(zhí)行環(huán)境從window改成對(duì)象{id: 42}
定時(shí)器的作用就是延遲執(zhí)行當(dāng)前函數(shù)的外部執(zhí)行環(huán)境,無論有沒有設(shè)置延遲時(shí)間

普通函數(shù)解釋:定義時(shí)this指向函數(shù)foo作用域,但是在定時(shí)器100毫秒之后執(zhí)行函數(shù)時(shí),此時(shí)this指向window對(duì)象

箭頭函數(shù)解釋:this始終指向定義時(shí)所在對(duì)象,也就是始終指向foo作用域

進(jìn)一步分析this

var handler = {
  id: "123456",

  init: function() {
    document.addEventListener("click",
      event => this.doSomething(event.type), false);
  },

  doSomething: function(type) {
    console.log("Handling " + type  + " for " + this.id);
  }
};
handler.init()// Handlingclickfor123456

箭頭函數(shù)的this始終指向handler,如果是普通函數(shù),this指向document

this指向的固定化,并不是因?yàn)榧^函數(shù)內(nèi)部有綁定this的機(jī)制,實(shí)際原因是箭頭函數(shù)根本沒有自己的this,導(dǎo)致內(nèi)部的this就是外層代碼塊的this。正是因?yàn)樗鼪]有this,所以也就不能用作構(gòu)造函數(shù)。

注意事項(xiàng)(綁定事件)

在IE678里面不支持addEventListener和removeEventListener,而是支持attchEvent和detachEvent兩個(gè)方法。

語法:target.attachEvent(“on”+type, listener);

attachEvent和addEventListener區(qū)別:

在attchEvent里面的this指向的不是事件的調(diào)用者,而是window(奇葩),而addEventListener指向的事件調(diào)用者。

attachEvent的type一定要加上on,不然沒效果

面試題

下面的面試題一、二、四都設(shè)計(jì)到引用問題,如果不是很好理解還可以理解成在 es5 中,永遠(yuǎn)是this 永遠(yuǎn)指向最后調(diào)用它的那個(gè)對(duì)象。摘錄鏈接

下面涉及指針應(yīng)用還有綁定之類的概念來自You Dont Konw JS鏈接

面試題一
this.x = 9;    // this refers to global "window" object here in the browser
var module = {
  x: 81,
  getX: function() { return this.x; }
};

module.getX(); // 81

var retrieveX = module.getX;
retrieveX();   
// returns 9 - The function gets invoked at the global scope

// Create a new function with "this" bound to module
// New programmers might confuse the
// global var x with module"s property x
var boundGetX = retrieveX.bind(module);
boundGetX(); // 81

retrieveX只是getX函數(shù)的引用,也就是只是getX的一個(gè)指針(getX的另一個(gè)指針是module.getX),所以retrieveX還是指向getX函數(shù)本身的

和上面類似的案例,下面的func只是函數(shù)引用,所以即使在函數(shù)內(nèi)部,還是執(zhí)行的函數(shù)本身,不受詞法作用域限制(箭頭函數(shù)則受限制)

document.getElementById( "div1" ).onclick = function(){
    console.log( this.id );// 輸出: div1
    var func = function(){ 
        console.log ( this.id );// 輸出: undefined
    } 
    func();
}; 
//修正后
document.getElementById( "div1" ).onclick = function(){
    var func = function(){ 
        console.log ( this.id );// 輸出: div1
    } 
    func.call(this);
}; 
function foo() {
    console.log( this.a );
}

var a = 2;
var o = { a: 3, foo: foo };
var p = { a: 4 };

o.foo(); // 3
(p.foo = o.foo)(); // 2
面試題二
var A = function( name ){ 
    this.name = name;
};
var B = function(){ 
    A.apply(this,arguments);
};
B.prototype.getName = function(){ 
    return this.name;
};
var b=new B("sven");
console.log( b.getName() ); // 輸出:  "sven"
面試題三

確實(shí),許多包中的函數(shù),和許多在JavaScript語言以及宿主環(huán)境中的內(nèi)建函數(shù),都提供一個(gè)可選參數(shù),通常稱為“環(huán)境(context)”,這種設(shè)計(jì)作為一種替代方案來確保你的回調(diào)函數(shù)使用特定的this而不必非得使用bind(..)。

舉例來說:

function foo(el) {
    console.log( el, this.id );
}

var obj = {
    id: "awesome"
};

// 使用`obj`作為`this`來調(diào)用`foo(..)`
[1, 2, 3].forEach( foo, obj ); // 1 awesome  2 awesome  3 awesome
面試題四

明確綁定 的優(yōu)先權(quán)要高于 隱含綁定

function foo() {
    console.log( this.a );
}

var obj1 = {
    a: 2,
    foo: foo
};

var obj2 = {
    a: 3,
    foo: foo
};

obj1.foo(); // 2
obj2.foo(); // 3

obj1.foo.call( obj2 ); // 3
obj2.foo.call( obj1 ); // 2

new綁定的優(yōu)先級(jí)高于隱含綁定(new和call/apply不能同時(shí)使用,所以new foo.call(obj1)是不允許的,也就是不能直接對(duì)比測(cè)試 new綁定 和 明確綁定)

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

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

相關(guān)文章

  • 前端最強(qiáng)面經(jīng)匯總

    摘要:獲取的對(duì)象范圍方法獲取的是最終應(yīng)用在元素上的所有屬性對(duì)象即使沒有代碼,也會(huì)把默認(rèn)的祖宗八代都顯示出來而只能獲取元素屬性中的樣式。因此對(duì)于一個(gè)光禿禿的元素,方法返回對(duì)象中屬性值如果有就是據(jù)我測(cè)試不同環(huán)境結(jié)果可能有差異而就是。 花了很長(zhǎng)時(shí)間整理的前端面試資源,喜歡請(qǐng)大家不要吝嗇star~ 別只收藏,點(diǎn)個(gè)贊,點(diǎn)個(gè)star再走哈~ 持續(xù)更新中……,可以關(guān)注下github 項(xiàng)目地址 https:...

    wangjuntytl 評(píng)論0 收藏0
  • 從一道面試,到“我可能看了假源碼”

    摘要:返回的綁定函數(shù)也能使用操作符創(chuàng)建對(duì)象這種行為就像把原函數(shù)當(dāng)成構(gòu)造器。同時(shí),將第一個(gè)參數(shù)以外的其他參數(shù),作為提供給原函數(shù)的預(yù)設(shè)參數(shù),這也是基本的顆?;A(chǔ)。 今天想談?wù)勔坏狼岸嗣嬖囶},我做面試官的時(shí)候經(jīng)常喜歡用它來考察面試者的基礎(chǔ)是否扎實(shí),以及邏輯、思維能力和臨場(chǎng)表現(xiàn),題目是:模擬實(shí)現(xiàn)ES5中原生bind函數(shù)。也許這道題目已經(jīng)不再新鮮,部分讀者也會(huì)有思路來解答。社區(qū)上關(guān)于原生bind的研...

    Carson 評(píng)論0 收藏0
  • 從一道面試,到“我可能看了假源碼”

    摘要:返回的綁定函數(shù)也能使用操作符創(chuàng)建對(duì)象這種行為就像把原函數(shù)當(dāng)成構(gòu)造器。同時(shí),將第一個(gè)參數(shù)以外的其他參數(shù),作為提供給原函數(shù)的預(yù)設(shè)參數(shù),這也是基本的顆粒化基礎(chǔ)。 今天想談?wù)勔坏狼岸嗣嬖囶},我做面試官的時(shí)候經(jīng)常喜歡用它來考察面試者的基礎(chǔ)是否扎實(shí),以及邏輯、思維能力和臨場(chǎng)表現(xiàn),題目是:模擬實(shí)現(xiàn)ES5中原生bind函數(shù)。也許這道題目已經(jīng)不再新鮮,部分讀者也會(huì)有思路來解答。社區(qū)上關(guān)于原生bind的研...

    rockswang 評(píng)論0 收藏0
  • 從一道面試,到“我可能看了假源碼”

    摘要:返回的綁定函數(shù)也能使用操作符創(chuàng)建對(duì)象這種行為就像把原函數(shù)當(dāng)成構(gòu)造器。同時(shí),將第一個(gè)參數(shù)以外的其他參數(shù),作為提供給原函數(shù)的預(yù)設(shè)參數(shù),這也是基本的顆?;A(chǔ)。 今天想談?wù)勔坏狼岸嗣嬖囶},我做面試官的時(shí)候經(jīng)常喜歡用它來考察面試者的基礎(chǔ)是否扎實(shí),以及邏輯、思維能力和臨場(chǎng)表現(xiàn),題目是:模擬實(shí)現(xiàn)ES5中原生bind函數(shù)。也許這道題目已經(jīng)不再新鮮,部分讀者也會(huì)有思路來解答。社區(qū)上關(guān)于原生bind的研...

    jlanglang 評(píng)論0 收藏0
  • 50道JavaScript基礎(chǔ)面試答案)

    摘要:事件中屬性等于。響應(yīng)的狀態(tài)為或者。同步在上會(huì)產(chǎn)生頁面假死的問題。表示聲明的變量未初始化,轉(zhuǎn)換為數(shù)值時(shí)為。但并非所有瀏覽器都支持事件捕獲。它由兩部分構(gòu)成函數(shù),以及創(chuàng)建該函數(shù)的環(huán)境。 1 介紹JavaScript的基本數(shù)據(jù)類型Number、String 、Boolean 、Null、Undefined Object 是 JavaScript 中所有對(duì)象的父對(duì)象數(shù)據(jù)封裝類對(duì)象:Object、...

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

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

0條評(píng)論

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