国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

JavaScript基礎(chǔ)心法——call apply bind

techstay / 575人閱讀

摘要:原文地址基礎(chǔ)心法歡迎。也就是說,這三個方法可以改變函數(shù)體內(nèi)部的指向。令為一個空列表。提供作為值并以作為參數(shù)列表,調(diào)用的內(nèi)部方法,返回結(jié)果。在外面?zhèn)魅氲闹禃薷牟⒊蔀橹怠UZ法其中,就是指向,是指定的參數(shù)。

原文地址:JavaScript基礎(chǔ)心法——call apply bind

歡迎star。

如果有錯誤的地方歡迎指正。

整理callapplybind這三個方法的的知識點(diǎn)。

之前這篇文章提到過this的各種情況,其中有一種情況就是通過callapplybind來將this綁定到指定的對象上。

也就是說,這三個方法可以改變函數(shù)體內(nèi)部this的指向。

這三個方法有什么區(qū)別呢?分別適合應(yīng)用在哪些場景中呢?

先舉個簡單的栗子 ~

var person = {
  name: "axuebin",
  age: 25
};
function say(job){
  console.log(this.name+":"+this.age+" "+job);
}
say.call(person,"FE"); // axuebin:25 FE
say.apply(person,["FE"]); // axuebin:25 FE
var sayPerson = say.bind(person,"FE");
sayPerson(); // axuebin:25 FE

對于對象person而言,并沒有say這樣一個方法,通過call/apply/bind就可以將外部的say方法用于這個對象中,其實(shí)就是將say內(nèi)部的this指向person這個對象。

call

call是屬于所有Function的方法,也就是Function.prototype.call

The call() method calls a function with a given this value and arguments provided individually.

call() 方法調(diào)用一個函數(shù), 其具有一個指定的this值和分別地提供的參數(shù)(參數(shù)的列表)。

它的語法是這樣的:

fun.call(thisArg[,arg1[,arg2,…]]);

其中,thisArg就是this指向,arg是指定的參數(shù)。

call的用處簡而言之就是可以讓call()中的對象調(diào)用當(dāng)前對象所擁有的function。

ECMAScript規(guī)范

ECMAScript規(guī)范中是這樣定義call的:

當(dāng)以thisArg和可選的arg1,arg2等等作為參數(shù)在一個func對象上調(diào)用call方法,采用如下步驟:

如果IsCallable(func)false, 則拋出一個TypeError異常。

argList為一個空列表。

如果調(diào)用這個方法的參數(shù)多余一個,則從arg1開始以從左到右的順序?qū)⒚總€參數(shù)插入為argList的最后一個元素。

提供thisArg作為this值并以argList作為參數(shù)列表,調(diào)用func[[Call]]內(nèi)部方法,返回結(jié)果。

call方法的length屬性是1。

在外面?zhèn)魅氲?b>thisArg值會修改并成為this值。thisArgundefinednull時它會被替換成全局對象,所有其他值會被應(yīng)用ToObject并將結(jié)果作為this值,這是第三版引入的更改。

使用call調(diào)用函數(shù)并且指定this
var obj = {
  a: 1
}
function foo(b, c){
  this.b = b;
  this.c = c;
  console.log(this.a + this.b + this.c);
}
foo.call(obj,2,3); // 6
call實(shí)現(xiàn)繼承

在需要實(shí)現(xiàn)繼承的子類構(gòu)造函數(shù)中,可以通過call調(diào)用父類構(gòu)造函數(shù)實(shí)現(xiàn)繼承。

function Person(name, age){
  this.name = name;
  this.age = age;
  this.say = function(){
    console.log(this.name + ":" + this.age);
  }
}
function Student(name, age, job){
  Person.call(this, name ,age);
  this.job = job;
  this.say = function(){
    console.log(this.name + ":" + this.age + " " + this.job);
  }
}
var me = new Student("axuebin",25,"FE");
console.log(me.say()); // axuebin:25 FE
apply

apply也是屬于所有Function的方法,也就是Function.prototype.apply

The apply() method calls a function with a given this value, and arguments provided as an array (or an array-like object).

apply() 方法調(diào)用一個函數(shù), 其具有一個指定的this值,以及作為一個數(shù)組(或類似數(shù)組的對象)提供的參數(shù)。

它的語法是這樣的:

fun.apply(thisArg, [argsArray]);

其中,thisArg就是this指向,argsArray是指定的參數(shù)數(shù)組。

通過語法就可以看出callapply的在參數(shù)上的一個區(qū)別:

call的參數(shù)是一個列表,將每個參數(shù)一個個列出來

apply的參數(shù)是一個數(shù)組,將每個參數(shù)放到一個數(shù)組中

ECMAScript規(guī)范

當(dāng)以thisArgargArray為參數(shù)在一個func對象上調(diào)用apply方法,采用如下步驟:

如果IsCallable(func)false, 則拋出一個TypeError異常 .

如果argArraynullundefined, 則

返回提供thisArg作為this值并以空參數(shù)列表調(diào)用func[[Call]]內(nèi)部方法的結(jié)果。

如果Type(argArray)不是Object, 則拋出一個TypeError異常 .

len為以"length"作為參數(shù)調(diào)用argArray[[Get]]內(nèi)部方法的結(jié)果。

nToUint32(len).

argList為一個空列表 .

index為0.

只要index<n就重復(fù)

indexNameToString(index).

nextArg為以indexName作為參數(shù)調(diào)用argArray[[Get]]內(nèi)部方法的結(jié)果。

nextArg作為最后一個元素插入到argList里。

設(shè)定indexindex + 1.

提供thisArg作為this值并以argList作為參數(shù)列表,調(diào)用func[[Call]]內(nèi)部方法,返回結(jié)果。

apply方法的length屬性是 2。

在外面?zhèn)魅氲?b>thisArg值會修改并成為this值。thisArgundefinednull時它會被替換成全局對象,所有其他值會被應(yīng)用ToObject并將結(jié)果作為this值,這是第三版引入的更改。

用法

在用法上applycall一樣,就不說了。

實(shí)現(xiàn)一個apply

參考鏈接:https://github.com/jawil/blog/issues/16

第一步,綁定上下文
Function.prototype.myApply=function(context){
  // 獲取調(diào)用`myApply`的函數(shù)本身,用this獲取
  context.fn = this;
  // 執(zhí)行這個函數(shù)
  context.fn();
  // 從上下文中刪除函數(shù)引用
  delete context.fn;
}

var obj ={
  name: "xb",
  getName: function(){
    console.log(this.name);
  }
}

var me = {
  name: "axuebin"
}

obj.getName(); // xb 
obj.getName.myApply(me); // axuebin

確實(shí)成功地將this指向了me對象,而不是本身的obj對象。

第二步,給定參數(shù)

上文已經(jīng)提到apply需要接受一個參數(shù)數(shù)組,可以是一個類數(shù)組對象,還記得獲取函數(shù)參數(shù)可以用arguments嗎?

Function.prototype.myApply=function(context){
  // 獲取調(diào)用`myApply`的函數(shù)本身,用this獲取
  context.fn = this;
  // 通過arguments獲取參數(shù)
  var args = arguments[1];
  // 執(zhí)行這個函數(shù),用ES6的...運(yùn)算符將arg展開
  context.fn(...args);
  // 從上下文中刪除函數(shù)引用
  delete context.fn;
}

var obj ={
  name: "xb",
  getName: function(age){
    console.log(this.name + ":" + age);
  }
}

var me = {
  name: "axuebin"
}

obj.getName(); // xb:undefined
obj.getName.myApply(me,[25]); // axuebin:25

context.fn(...arg)是用了ES6的方法來將參數(shù)展開,如果看過上面那個鏈接,就知道這里不通過...運(yùn)算符也是可以的。

原博主通過拼接字符串,然后用eval執(zhí)行的方式將參數(shù)傳進(jìn)context.fn中:

for (var i = 0; i < args.length; i++) {
  fnStr += i == args.length - 1 ? args[i] : args[i] + ",";
}
fnStr += ")";//得到"context.fn(arg1,arg2,arg3...)"這個字符串在,最后用eval執(zhí)行
eval(fnStr); //還是eval強(qiáng)大
第三步,當(dāng)傳入apply的this為null或者為空時

我們知道,當(dāng)apply的第一個參數(shù),也就是this的指向為null時,this會指向window。知道了這個,就簡單了~

Function.prototype.myApply=function(context){
  // 獲取調(diào)用`myApply`的函數(shù)本身,用this獲取,如果context不存在,則為window
  var context = context || window;
  context.fn = this;
  //獲取傳入的數(shù)組參數(shù)
  var args = arguments[1];
  if (args == undefined) { //沒有傳入?yún)?shù)直接執(zhí)行
    // 執(zhí)行這個函數(shù)
    context.fn()
  } else {
    // 執(zhí)行這個函數(shù)
    context.fn(...args);
  }
  // 從上下文中刪除函數(shù)引用
  delete context.fn;
}

var obj ={
  name: "xb",
  getName: function(age){
    console.log(this.name + ":" + age);
  }
}

var name = "window.name";

var me = {
  name: "axuebin"
}

obj.getName(); // xb:25
obj.getName.myApply(); // window.name:undefined
obj.getName.myApply(null, [25]); // window.name:25
obj.getName.myApply(me, [25]); // axuebin:25
第四步 保證fn函數(shù)的唯一性

ES6中新增了一種基礎(chǔ)數(shù)據(jù)類型Symbol

const name = Symbol();
const age = Symbol();
console.log(name === age); // false

const obj = {
  [name]: "axuebin",
  [age]: 25
}

console.log(obj); // {Symbol(): "axuebin", Symbol(): 25}
console.log(obj[name]); // axuebin

所以我們可以通過Symbol來創(chuàng)建一個屬性名。

var fn = Symbol();
context[fn] = this;
完整的apply
Function.prototype.myApply=function(context){
  // 獲取調(diào)用`myApply`的函數(shù)本身,用this獲取,如果context不存在,則為window
  var context = context || window;
  var fn = Symbol();
  context[fn] = this;
  //獲取傳入的數(shù)組參數(shù)
  var args = arguments[1];
  if (args == undefined) { //沒有傳入?yún)?shù)直接執(zhí)行
    // 執(zhí)行這個函數(shù)
    context[fn]()
  } else {
    // 執(zhí)行這個函數(shù)
    context[fn](...args);
  }
  // 從上下文中刪除函數(shù)引用
  delete context.fn;
}

這樣就是一個完整的apply了,我們來測試一下:

var obj ={
  name: "xb",
  getName: function(age){
    console.log(this.name + ":" + age);
  }
}

var name = "window.name";

var me = {
  name: "axuebin"
}

obj.getName(); // xb:25
obj.getName.myApply(); // window.name:undefined
obj.getName.myApply(null, [25]); // window.name:25
obj.getName.myApply(me, [25]); // axuebin:25

ok 沒啥毛病 ~

再次感謝1024大佬 ~

bind

The bind() method creates a new function that, when called, has its this keyword set to the provided value, with a given sequence of arguments preceding any provided when the new function is called.

bind()方法創(chuàng)建一個新的函數(shù), 當(dāng)被調(diào)用時,將其this關(guān)鍵字設(shè)置為提供的值,在調(diào)用新函數(shù)時,在任何提供之前提供一個給定的參數(shù)序列。

語法:

fun.bind(thisArg[, arg1[, arg2[, ...]]])

其中,thisArg就是this指向,arg是指定的參數(shù)。

可以看出,bind會創(chuàng)建一個新函數(shù)(稱之為綁定函數(shù)),原函數(shù)的一個拷貝,也就是說不會像callapply那樣立即執(zhí)行。

當(dāng)這個綁定函數(shù)被調(diào)用時,它的this值傳遞給bind的一個參數(shù),執(zhí)行的參數(shù)是傳入bind的其它參數(shù)和執(zhí)行綁定函數(shù)時傳入的參數(shù)。

用法

當(dāng)我們執(zhí)行下面的代碼時,我們希望可以正確地輸出name,然后現(xiàn)實(shí)是殘酷的

function Person(name){
  this.name = name;
  this.say = function(){
    setTimeout(function(){
      console.log("hello " + this.name);
    },1000)
  }
}
var person = new Person("axuebin");
person.say(); //hello undefined

這里this運(yùn)行時是指向window的,所以this.nameundefined,為什么會這樣呢?看看MDN的解釋:

由setTimeout()調(diào)用的代碼運(yùn)行在與所在函數(shù)完全分離的執(zhí)行環(huán)境上。這會導(dǎo)致,這些代碼中包含的 this 關(guān)鍵字在非嚴(yán)格模式會指向 window。

有一個常見的方法可以使得正確的輸出:

function Person(name){
  this.name = name;
  this.say = function(){
    var self = this;
    setTimeout(function(){
      console.log("hello " + self.name);
    },1000)
  }
}
var person = new Person("axuebin");
person.say(); //hello axuebin

沒錯,這里我們就可以用到bind了:

function Person(name){
  this.name = name;
  this.say = function(){
    setTimeout(function(){
      console.log("hello " + this.name);
    }.bind(this),1000)
  }
}
var person = new Person("axuebin");
person.say(); //hello axuebin
MDN的Polyfill
Function.prototype.bind = function (oThis) {
  var aArgs = Array.prototype.slice.call(arguments, 1);
  var fToBind = this;
  var fNOP = function () {};
  var fBound = function () {
    fBound.prototype = this instanceof fNOP ? new fNOP() : fBound.prototype;
    return fToBind.apply(this instanceof fNOP ? this : oThis || this, aArgs )
  }   
  if( this.prototype ) {
    fNOP.prototype = this.prototype;
  }
  return fBound;
}
總結(jié)

三者都是用來改變函數(shù)的this指向

三者的第一個參數(shù)都是this指向的對象

bind是返回一個綁定函數(shù)可稍后執(zhí)行,callapply是立即調(diào)用

三者都可以給定參數(shù)傳遞

call給定參數(shù)需要將參數(shù)全部列出,apply給定參數(shù)數(shù)組

感謝

不用call和apply方法模擬實(shí)現(xiàn)ES5的bind方法

深入淺出妙用 Javascript 中 apply、call、bind

回味JS基礎(chǔ):call apply 與 bind

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

轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/91926.html

相關(guān)文章

  • JavaScript基礎(chǔ)心法——this

    摘要:原文地址基礎(chǔ)心法歡迎。作為一個構(gòu)造函數(shù)被綁定到正在構(gòu)造的新對象。通過構(gòu)造函數(shù)創(chuàng)建一個對象其實(shí)執(zhí)行這樣幾個步驟創(chuàng)建新對象將指向這個對象給對象賦值屬性方法返回所以就是指向創(chuàng)建的這個對象上。 原文地址:JavaScript基礎(chǔ)心法——this 歡迎star。 如果有錯誤的地方歡迎指正。 看看這個有著深不可測的魔力的this到底是個什么玩意兒 ~ 什么是this 在傳統(tǒng)面向?qū)ο蟮恼Z言中,比如...

    hover_lew 評論0 收藏0
  • 細(xì)數(shù) JavaScript 實(shí)用黑科技(二)

    摘要:前言書接上文細(xì)數(shù)實(shí)用黑科技一本文介紹獨(dú)孤九劍和兩篇最高內(nèi)功心法。可以將變量轉(zhuǎn)換為布爾值。可以把任何類型的值轉(zhuǎn)換為布爾值,并且只有當(dāng)這個變量的值為的時候才會返回,其他情況都返回。同樣的,函數(shù)體內(nèi)部聲明的函數(shù),作用域綁定函數(shù)體內(nèi)部。 showImg(https://segmentfault.com/img/remote/1460000016507838); 前言 書接上文:細(xì)數(shù) JavaS...

    馬忠志 評論0 收藏0
  • JS基礎(chǔ)篇--callapplybind方法詳解

    摘要:首先我們可以通過給目標(biāo)函數(shù)指定作用域來簡單實(shí)現(xiàn)方法保存,即調(diào)用方法的目標(biāo)函數(shù)考慮到函數(shù)柯里化的情況,我們可以構(gòu)建一個更加健壯的這次的方法可以綁定對象,也支持在綁定的時候傳參。原因是,在中,多次是無效的。而則會立即執(zhí)行函數(shù)。 bind 是返回對應(yīng)函數(shù),便于稍后調(diào)用;apply 、call 則是立即調(diào)用 。 apply、call 在 javascript 中,call 和 apply 都是...

    lastSeries 評論0 收藏0
  • javascript 基礎(chǔ)call, apply, bind

    摘要:系統(tǒng),扎實(shí)的語言基礎(chǔ)是一個優(yōu)秀的前端工程師必須具備的。第一個參數(shù)為調(diào)用函數(shù)時的指向,隨后的參數(shù)則作為函數(shù)的參數(shù)并調(diào)用,也就是。和的區(qū)別只有一個,就是它只有兩個參數(shù),而且第二個參數(shù)為調(diào)用函數(shù)時的參數(shù)構(gòu)成的數(shù)組。 系統(tǒng),扎實(shí)的 javascript 語言基礎(chǔ)是一個優(yōu)秀的前端工程師必須具備的。在看了一些關(guān)于 call,apply,bind 的文章后,我還是打算寫下這篇總結(jié),原因其實(shí)有好幾個。...

    xeblog 評論0 收藏0
  • javascript基礎(chǔ):this關(guān)鍵字

    摘要:它代表函數(shù)運(yùn)行時,自動生成的一個內(nèi)部對象,只能在函數(shù)內(nèi)部使用類似的還有。總結(jié)關(guān)鍵字就是,誰調(diào)用我,我就指向誰。注意由于已經(jīng)被定義為函數(shù)內(nèi)的一個變量。因此通過關(guān)鍵字定義或者將聲明為一個形式參數(shù),都將導(dǎo)致原生的不會被創(chuàng)建。 題目 封裝函數(shù) f,使 f 的 this 指向指定的對象 。 輸入例子 bindThis(function(a, b) { return this.test +...

    LeoHsiun 評論0 收藏0

發(fā)表評論

0條評論

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