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

資訊專欄INFORMATION COLUMN

關于 bind 你可能需要了解的知識點以及使用場景

ls0609 / 1643人閱讀

摘要:語法是這樣樣子的當綁定函數(shù)被調用時,該參數(shù)會作為原函數(shù)運行時的指向。當使用對象的方法時,需要引用對象,你可能需要顯式地把綁定到回調函數(shù)以便繼續(xù)使用對象。中方法簡介備忘中的,以及中方法的使用與實現(xiàn)

不看不知道,一看嚇一跳,已經(jīng)整整一個月沒有更新 underscore 源碼解讀系列文章了。前面我們已經(jīng)完成了 Object ,Array,Collection 上的擴展方法的源碼剖析,本文開始來解讀 Function 上的擴展方法。

完整的 underscore 源碼解讀系列文章請移步 https://github.com/hanzichi/u...,覺得還闊以的話,給個 star 鼓勵下樓主唄 ^_^

bind 簡介

Ok,今天要講的正是 bind。關于 bind,可以先移步樓主以前寫的文章 ECMAScript 5(ES5) 中 bind 方法簡介備忘,有個基本的概念。

bind() 方法會創(chuàng)建一個新函數(shù),當這個新函數(shù)被調用時,它的 this 值是傳遞給 bind() 的第一個參數(shù), 它的參數(shù)是 bind() 的其他參數(shù)和其原本的參數(shù)。

語法是這樣樣子的:

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

thisArg 當綁定函數(shù)被調用時,該參數(shù)會作為原函數(shù)運行時的 this 指向。當使用 new 操作符調用綁定函數(shù)時,該參數(shù)無效。

arg1, arg2, ... (可選)當綁定函數(shù)被調用時,這些參數(shù)加上綁定函數(shù)本身的參數(shù)會按照順序作為原函數(shù)運行時的參數(shù)。

參數(shù)

bind 的第一個參數(shù)會作為原函數(shù)運行時的 this 指向,不多說;而第二個開始的參數(shù)是可選的,當綁定函數(shù)被調用時,這些參數(shù)加上綁定函數(shù)本身的參數(shù)會按照順序作為原函數(shù)運行時的參數(shù)。怎么理解?

function fn(a, b, c) {
  return a + b + c;
}

var _fn = fn.bind(null, 10);
var ans = _fn(20, 30); // 60

fn 函數(shù)需要三個參數(shù),_fn 函數(shù)將 10 作為默認的第一個參數(shù),所以只需要傳入兩個參數(shù)即可,如果你不小心傳入了三個參數(shù),放心,也只會取前兩個。

function fn(a, b, c) {
  return a + b + c;
}

var _fn = fn.bind(null, 10);
var ans = _fn(20, 30, 40); // 60

這有啥用呢?如果某些函數(shù),前幾個參數(shù)已經(jīng) “內定” 了,我們便可以用 bind 返回一個新的函數(shù)。也就是說,bind() 能使一個函數(shù)擁有預設的初始參數(shù)。這些參數(shù)(如果有的話)作為 bind() 的第二個參數(shù)跟在 this 后面,之后它們會被插入到目標函數(shù)的參數(shù)列表的開始位置,傳遞給綁定函數(shù)的參數(shù)會跟在它們的后面。

function list() {
  return Array.prototype.slice.call(arguments);
}

var list1 = list(1, 2, 3); // [1, 2, 3]

// Create a function with a preset leading argument
var leadingThirtysevenList = list.bind(undefined, 37);

var list2 = leadingThirtysevenList(); // [37]
var list3 = leadingThirtysevenList(1, 2, 3); // [37, 1, 2, 3]
new

使用 bind 返回的結果還是個 function,是個 function 就可以被 new 運算符調用,那么結果呢?規(guī)范中說的很清楚了,當使用 new 操作符調用綁定函數(shù)時,bind 的第一個參數(shù)無效。

function Person(name, age) {
  this.name = name;
  this.age = age;
}

var _Person = Person.bind({});
var p = new _Person("hanzichi", 30); // Person {name: "hanzichi", age: 30}

一般我們不會去這么用,但是如果要寫個 bind 的 polyfill(http://caniuse.com/#search=bind),還是需要考慮用 new 調用的情況。

我們也可以設置默認值(參考上一小節(jié)),原先提供的那些參數(shù)仍然會被前置到構造函數(shù)調用的前面。

function Person(name, age) {
  this.name = name;
  this.age = age;
}

var _Person = Person.bind(null, "hanzichi");
var p = new _Person(30); // Person {name: "hanzichi", age: 30}
配合 setTimeout

什么時候容易丟失 this 指向?恩,setTimeout 是一個場景,很容易把 this 指向 window,當然,setInterval 也是一樣。當使用對象的方法時,需要 this 引用對象,你可能需要顯式地把 this 綁定到回調函數(shù)以便繼續(xù)使用對象。

var canvas = {
  render: function() {
    this.update();
    this.draw();
  },

  update: function() {
    // ...
  },

  draw: function() {
    // ...
  }
};

window.setInterval(canvas.render, 1000 / 60);

用 canvas 寫特效或者做游戲時經(jīng)常會碰到類似的問題。上面的代碼是有問題的,render 方法中的 this 其實被指向了 window!我們可以用 bind,顯式地把 this 綁定到回調函數(shù)以便繼續(xù)使用該對象。

window.setInterval(canvas.render.bind(canvas), 1000);

類似的情況還有 dom 的事件監(jiān)聽,一不小心可能 this 就被指向了 dom 元素??梢詤⒖枷乱郧白?bigrender 時寫的這部分代碼 https://github.com/hanzichi/h...。

tip

bind 還能做一些有意思的事情。

通常來說,將一個類數(shù)組轉為數(shù)組,我們會用 slice(ie9- 不支持)。參考 https://github.com/hanzichi/u...

var slice = Array.prototype.slice;

// slice.apply(arguments);
// slice(arguments, 1);

bind 能讓調用變的更加簡單。

// same as "slice" in the previous example
var unboundSlice = Array.prototype.slice;
var slice = Function.prototype.call.bind(unboundSlice);

// ...

slice(arguments);
// slice(arguments, 1);

再舉個類似的例子,比如說我們要添加事件到多個節(jié)點,for 循環(huán)當然沒有任何問題,我們還可以 “剽竊” forEach 方法:

Array.prototype.forEach.call(document.querySelectorAll("input[type="button"]"), function(el){
  el.addEventListener("click", fn);
});

更進一步,我們可以用 bind 將函數(shù)封裝的更好:

var unboundForEach = Array.prototype.forEach
  , forEach = Function.prototype.call.bind(unboundForEach);

forEach(document.querySelectorAll("input[type="button"]"), function (el) {
  el.addEventListener("click", fn);
});

同樣類似的,我們可以將 x.y(z) 變成 y(x,z) 的形式:

var obj = {
  num: 10,
  getCount: function() {
    return this.num;
  }
};

var unboundBind = Function.prototype.bind
  , bind = Function.prototype.call.bind(unboundBind);

var getCount = bind(obj.getCount, obj);
console.log(getCount());  // 10

再舉個栗子。每隔一秒在控制臺打印 1-5,看起來是道考察閉包的經(jīng)典題目。

for(var i = 1; i <= 5; i++) {
  !function(i) {
    setTimeout(function() {
      console.log(i);
    }, i * 1000);
  }(i);
}

ES6 下能用 let

for(let i = 1; i <= 5; i++) {
  setTimeout(function() {
    console.log(i);
  }, i * 1000);
}

也可以用 bind,瞬間逼格提升:

for(var i = 1; i <= 5; i++) {
  setTimeout(console.log.bind(console, i), i * 1000);
}
Read more

關于 bind 的介紹就到這里,下一篇文章將結合 underscore 來講講如何實現(xiàn)一個 bind 的 polyfill。

Function.prototype.bind()

ECMAScript 5(ES5) 中 bind 方法簡介備忘

Javascript 中的 Bind ,Call 以及 Apply

Javascript 中 bind() 方法的使用與實現(xiàn)

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

轉載請注明本文地址:http://www.ezyhdfw.cn/yun/80084.html

Failed to recv the data from server completely (SIZE:0/8, REASON:closed)