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

資訊專欄INFORMATION COLUMN

JavaScript的this值

charles_paul / 1963人閱讀

摘要:函數(shù)的調(diào)用者是異步函數(shù),不會為回調(diào)函數(shù)指定值。值為表示在全局對象下執(zhí)行該函數(shù)執(zhí)行方法,返回一個函數(shù)作為回調(diào)函數(shù),并且將需要向它傳遞的作為參數(shù)。

重要

JavaScript的this是有函數(shù)求值是的調(diào)用者決定的

JavaScript的this是有函數(shù)求值是的調(diào)用者決定的

JavaScript的this是有函數(shù)求值是的調(diào)用者決定的

函數(shù)中的this

函數(shù)中的this在調(diào)用時才有意義,函數(shù)的調(diào)用者決定函數(shù)中this的指向,每個函數(shù)調(diào)用時都會有this屬性。

function Point2D(x, y) {
  this.x = x;
  this.y = y;
}
Point2D.prototype.showLength = function() {
  var length = Math.sqrt(Math.pow(this.x, 2) + Math.pow(this.y, 2));
  console.log(length);
};
Point2D.prototype.showLengthAsync = function() {
  var self = this;   // 將this的值保存下來,傳入異步函數(shù)

  setTimeout(function() {  // setTimeout是異步函數(shù),在調(diào)用回調(diào)函數(shù)時沒有指定匿名函數(shù)的this,
      self.showLength();  //因為回調(diào)函數(shù)沒有指定this,非嚴格模式下默認指向全局對象
  }, 1000);
};

var x = 30, y = 40;
var p = new Point2D(3, 4);
var f = Point2D.prototype.showLength;

1.f():輸出50,因為函數(shù)Point2D.prototype.showLength的調(diào)用者是變量f,變量f、xy、Ponit2D函數(shù)在同一個對象中。

所以函數(shù)Point2D.prototype.showLengththis指向的是包含變量f、xy、Ponit2D函數(shù)的對象。

this.x = 30,this.y = 40,所以f()是輸出50;

        Point2D.prototype.showLength = function() {
              var length = Math.sqrt(Math.pow(this.x, 2) + Math.pow(this.y, 2));
              console.log(length);
            };

2.setTimeout(p.showLength, 500); :延時500ms后輸出50。函數(shù)p.showLength的調(diào)用者是異步函數(shù)setTimeoutsetTimeout不會為回調(diào)函數(shù)指定this值。

在非嚴格模式下,p.showLength中的this默認指向全局變量

this.x = 30,this.y = 40,所以setTimeout(p.showLength, 500)延時500ms后輸出50;

借用bind()方法可以將函數(shù)綁定到對象上,即將函數(shù)內(nèi)的this指向bind(p)方法中傳入的p對象

setTimeout(p.showLength.bind(p), 500);    // 延時500ms后輸出5,因為函數(shù)p.showLength指向?qū)ο髉,p的x屬性為3,y屬性為4

3.p.showLengthAsync();: 延時1000ms后輸出5。

Point2D.prototype.showLengthAsync = function() {
  var self = this;   // 將this的值保存下來,傳入異步函數(shù)

  setTimeout(function() {  // setTimeout是異步函數(shù),在調(diào)用回調(diào)函數(shù)時沒有指定匿名函數(shù)的this,
      self.showLength();  //因為回調(diào)函數(shù)沒有指定this,非嚴格模式下默認指向全局對象
  }, 1000);
};

p.showLengthAsync函數(shù)的調(diào)用者是p對象本身,由于setTimeout不會為回調(diào)函數(shù)指定this值。所以在p.showLengthAsync函數(shù)中使用變量selfp.showLengthAsync函數(shù)調(diào)用的this值(即對象p)保存下來

回調(diào)函數(shù)中才可以利用變量self訪問到對象p,完成正確調(diào)用;

4.箭頭函數(shù)

箭頭函數(shù)很特殊,箭頭函數(shù)中沒有定義this,所以可以使用外層函數(shù)的this。

Point2D.prototype.showLengthAsync = function() {
  setTimeout( () => this.showLength(), 1000);   // 箭頭函數(shù)沒有定義this,可以訪問外層函數(shù)的this
};
call()

函數(shù)的call()方法可以指定函數(shù)調(diào)用時的this。函數(shù)中調(diào)用時的this值是可以改變的

并且,call()方法可以從第二個參數(shù)開始,指定傳入調(diào)用函數(shù)的參數(shù),以逗號分隔(多個原始形式的參數(shù))

function Point2D(x, y) {
  this.x = x;
  this.y = y;
}
Point2D.prototype.showLength = function() {
  var length = Math.sqrt(Math.pow(this.x, 2) + Math.pow(this.y, 2));
  console.log(length);
};

var p = new Point2D(1, 1);
console.log(p.showLength());  // ==> 1.4142...   調(diào)用p.length方法的是p對象本身,所以this.x和this.y均等于1

var obj = {x: 3, y: 4};
console.log(p.showLength.call(obj));   // ==> 5  使用函數(shù)p.showLength的call()方法改變函數(shù)調(diào)用時this的指向,
                                       //使其指向?qū)ο髈bj,所以this.x=3,this.y=4

function foo() {
  // 使用Array.prototype.slice函數(shù)的call()方法指定函數(shù)調(diào)用時的this指向arguments對象,將其切分為數(shù)組
  var args = Array.prototype.slice.call(arguments);

  console.log(Array.isArray(arguments));  // false
  console.log(Array.isArray(args));   //  true
}

call()的作用:改變當前函數(shù)調(diào)用時的this

apply()

函數(shù)的apply()方法與call()方法作用完全一致,只是在調(diào)用時傳入的參數(shù)有區(qū)別:

call()方法:第一個參數(shù)接收新的this值,后面的參數(shù)逗號分隔,逐個排列,傳入調(diào)用函數(shù)中

apply()方法:第一個參數(shù)接收新的this值,第二個參數(shù)接收一個數(shù)組,將數(shù)組整體作為參數(shù)傳入調(diào)用函數(shù)中

// 定義一個函數(shù),實現(xiàn)一種變換,將傳入其中的函數(shù)中參數(shù)的順序顛倒
function __reverseArgs__(fn) {
  return function() {
    var args = Array.prototype.slice.call(arguments);
    
    return fn.apply(this, args.reverse());  // 這里的this表示這個匿名函數(shù)的調(diào)用者
  };
}
var foo = function() {console.log(Array.from(arguments));};
var foo2 = __reverseArgs__(foo);
foo2(1, 2, 3, 4);

注意return fn.apply(this, args.reverse());中的this。因為__reverseArgs__(fn)函數(shù)返回一個新的函數(shù),apply()中的this指向調(diào)用這個新函數(shù)的對象。

foo2接收了__reverseArgs__(foo)返回的新函數(shù),調(diào)用foo2(1, 2, 3, 4)時,因為foo2在全局對象下,所以this的值是全局對象。

__reverseArgs__(fn)方法應(yīng)該只改變傳入函數(shù)中參數(shù)的順序,不改變原來函數(shù)調(diào)用的作用域。所以使用this將函數(shù)的調(diào)用改回傳入函數(shù)的作用域。

bind()

bind()方法與call()apply()方法的最大區(qū)別在于返回值:call()apply()都會立即執(zhí)行,返回結(jié)果;bind()方法會返回一個函數(shù),并且可以通過bind()向函數(shù)中傳遞已經(jīng)確定的參數(shù),對于異步調(diào)用很有幫助。

function add(x, y) {
  return x + y;
}
// call()和apply()會立即執(zhí)行;bind()方法會返回一個函數(shù)對象
console.log(add.call(null, 1, 2));   // ==> 3 ,使用call()方法在全局對象下對傳入的參數(shù)1,2執(zhí)行函數(shù)
console.log(add.apply(null, [1, 2]));   // ==> 3 apply()方法在全局對象下對傳入的參數(shù)1,2執(zhí)行函數(shù)
console.log(add.bind(null, 1, 2));   // ==> function () { [native code] }, 返回一個函數(shù)
// 傳入兩個參數(shù)
let add1 = add.bind(null, 1, 2);  // bind()方法執(zhí)行時,將1和2對應(yīng)傳遞給x,y,返回一個函數(shù)。再調(diào)用返回的函數(shù)時,不用再傳遞參數(shù)
console.log(add1());         //  ==> 3  為傳遞參數(shù),直接調(diào)用,使用bind()時傳入的參數(shù)值

// 傳入一個參數(shù)
let add2 = add.bind(null, 1);   //bind()時只傳遞一個參數(shù)1給x,返回一個函數(shù),在調(diào)用返回函數(shù)時只需炫迪一個參數(shù)給y即可
console.log(add2(3));    //  ==> 4  只需傳遞一個參數(shù)給y即可

// 不傳遞參數(shù)
let add3 = add.bind(null);    //調(diào)用bind()時不傳遞參數(shù),返回一個函數(shù),在調(diào)用返回函數(shù)時要傳遞2個參數(shù)
console.log(add3(2, 3));   // ==> 5  需要傳遞兩個參數(shù),與調(diào)用原函數(shù)沒有區(qū)別。。。不建議使用

可以看出bind()的最大用處在于返回一個函數(shù),并且可以向函數(shù)內(nèi)傳遞確定的參數(shù)值(在bind()執(zhí)行時時便已經(jīng)確定的參數(shù))。調(diào)用返回的函數(shù)時,無需再傳入bind()時傳入的參數(shù)---實現(xiàn)函數(shù)的部分調(diào)用

應(yīng)用場景:類似于setTimeout(fn, 1000);的異步函數(shù),需要一個函數(shù)作為參數(shù),在1s后執(zhí)行。有時對于已經(jīng)知道fn調(diào)用時傳入的參數(shù)值時,便可以使用bind(),先將參數(shù)傳遞進去,返回一個函數(shù);等待時間到后,無需再向該函數(shù)傳入?yún)?shù),立即執(zhí)行即可

function setBodyState(state) {
  document.body.className = state;
}
setBodyState.call(null, "state1");   // 立即執(zhí)行setBodyState函數(shù),將document.body.className設(shè)置為"state1"。
                                    // this值為null表示在全局對象下執(zhí)行該函數(shù)
setTimeout(setBodyState.bind(null, "state2"), 1500);  // 執(zhí)行bind()方法,返回一個函數(shù)作為回調(diào)函數(shù),并且將需要向它傳遞
                                      //的"state2"作為參數(shù)。1500ms后立即執(zhí)行返回的函數(shù)即可,無需再傳入?yún)?shù)

bind()方法在異步函數(shù)中的應(yīng)用,主要由于其返回一個函數(shù),并且可以傳入?yún)?shù)值的特性,可以減少異步函數(shù)調(diào)用的部分問題。

高階函數(shù)實例 Closure中訪問外部函數(shù)的arguments、this、形參和局部變量
// __multi__()抽象一個過程,將傳入的函數(shù)進行擴展,使其第一個參數(shù)接收類數(shù)組
// 調(diào)用原來的方法fn對每個第一個數(shù)組參數(shù)中的每個元素執(zhí)行fn方法
function __multi__(fn) {
  return function(arrayLike, ...args) {
    return Array.from(arrayLike).map(item => fn(item, ...args));
  };
}

function __multi__(fn) {
  return function(arrayLike, ...args) {   // 返回一個函數(shù)(創(chuàng)建一個Closure),返回的函數(shù)接收夜歌類數(shù)組對象和rest參數(shù)作為參數(shù)
    return Array.from(arrayLike).map(function(value) {
      return fn(value, ...args);
    });
  };
}

function add(x, y) { return x + y;}
var add2 = __multi__(add);
console.log(add2([1,2,3], 4));  // ==> [5, 6, 7]

1.注意map()方法如果需要返回值,一定要在傳入map()的函數(shù)中返回值,因為默認的返回值是undefined`
2.Closure中對于外層函數(shù)的局部變量、形參、實參對象argumentsthis的訪問問題:

__multi__()返回一個函數(shù)(創(chuàng)建一個Closure),返回的函數(shù)保留對外層函數(shù)作用域的訪問能力

this值和實參對象arguments是根據(jù)調(diào)用函數(shù)時確定的,如果要在Closure中訪問到調(diào)用時的thisarguments對象,需要將其保存在外部函數(shù)局部作用域的變量中。

function __multi__(fn) {
  var self = this;
  var outerArgs = arguments;
  return function(arrayLike, ...args) {
    return Array.from(arrayLike).map(function(value) {
      console.log(self);    // 可以訪問到外層函數(shù)的調(diào)用者
      console.log(outerArgs);  //可以訪問到外層函數(shù)的實參列表,相當于訪問外層函數(shù)的局部變量
      
      console.log(this);   // 訪問到的this值是返回函數(shù)的調(diào)用者
      console.log(arguments);  // 訪問到的arguments是傳入返回函數(shù)的實參
      
      return fn(value, ...args);   // 可以訪問到外部函數(shù)的形參  
    });
  };
}

Closure中可以訪問到外部函數(shù)的形參(形參的特性與局部變量相同)

function __multi__(fn, a = 2) {
  console.log(arguments[0]);
  return function(arrayLike, ...args) {
    return Array.from(arrayLike).map(function(value) {
      console.log(a);    // 可以訪問到外層函數(shù)的形參a
      return fn(value, ...args);   // 可以訪問到外部函數(shù)的形參fn
    });
  };
}

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

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

相關(guān)文章

  • 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)鍵字計算為當前執(zhí)行上下文的屬性的值。毫無疑問它將指向了這個前置的對象。構(gòu)造函數(shù)也是同理。嚴格模式無論調(diào)用位置,只取顯式給定的上下文綁定的,通過方法傳入的第一參數(shù),否則是。其實并不屬于特殊規(guī)則,是由于各種事件監(jiān)聽定義方式本身造成的。 this 是 JavaScript 中非常重要且使用最廣的一個關(guān)鍵字,它的值指向了一個對象的引用。這個引用的結(jié)果非常容易引起開發(fā)者的誤判,所以必須對這個關(guān)...

    TerryCai 評論0 收藏0
  • JavaScript深入淺出第1課:箭頭函數(shù)中this究竟是什么鬼?

    摘要:箭頭函數(shù)沒有自己的值,箭頭函數(shù)中所使用的來自于函數(shù)作用域鏈。使用箭頭函數(shù)打印對于內(nèi)層函數(shù),它本身并沒有值,其使用的來自作用域鏈,來自更高層函數(shù)的作用域。 《JavaScript 深入淺出》系列: JavaScript 深入淺出第 1 課:箭頭函數(shù)中的 this 究竟是什么鬼? JavaScript 深入淺出第 2 課:函數(shù)是一等公民是什么意思呢? 普通函數(shù)與箭頭函數(shù) 普通函數(shù)指的是...

    MRZYD 評論0 收藏0
  • 關(guān)于JavaScriptthis理解

    摘要:想想也是難以置信,這應(yīng)該全歸功于對框架的依賴,促使助長了自己對學(xué)習(xí)的懈怠。真正的成了離職就失業(yè)的尷尬境地。我們接下來來了解下中的的使用和作用。以前對中的理解很簡單粗暴誰調(diào)用就指向誰。如果例題中有不對的地方希望予以指教留言評論 前言 使用JavaScript有很長一段時間了,但是以前過多都是使用,從不去及理解其中原理,單單只是去生拼硬湊。這樣的開發(fā)居然做了2年。匪夷所思居然項目中Java...

    lindroid 評論0 收藏0
  • 如何理解JavaScriptthis關(guān)鍵字

    摘要:原文鏈接參考深入理解原型和閉包完結(jié)王福朋博客園中的作用域詳解博客園 前言 王福朋老師的 JavaScript原型和閉包系列 文章看了不下三遍了,最為一個初學(xué)者,每次看的時候都會有一種 大徹大悟 的感覺,而看完之后卻總是一臉懵逼。原型與閉包 可以說是 JavaScirpt 中理解起來最難的部分了,當然,我也只是了解到了一些皮毛,對于 JavaScript OOP 更是缺乏經(jīng)驗。這里我想總...

    Yangder 評論0 收藏0
  • javascript對象不完全探索記錄02:瘋狂打call!給誰打call?打什么call?

    摘要:注意該方法的作用和方法類似,只有一個區(qū)別,就是方法接受的是若干個參數(shù)的列表,而方法接受的是一個包含多個參數(shù)的數(shù)組。指定的參數(shù)列表。返回值返回值是你調(diào)用的方法的返回值,若該方法沒有返回值,則返回。 溫馨提示:作者的爬坑記錄,對你等大神完全沒有價值,別在我這浪費生命溫馨提示-續(xù):打call原本是屬于我們偶像宅文化中的專業(yè)名詞,指的是飯們在看live時在臺下配合愛豆演出的節(jié)奏喊口號,舉例:超...

    Shimmer 評論0 收藏0

發(fā)表評論

0條評論

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