【JS腳丫系列】重溫bind

概念

bind() 方法會返回一個新函數(稱爲綁定函數),綁定函數與原函數(使用bind()的函數)具備相同的函數體,可是綁定函數有新的this值和參數。瀏覽器

說白了,bind()就是建立一個有着新this和實參的函數。app

語法:

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

thisArgdom

綁定函數中this的指向。能夠是null,undefined,{},或其餘任意對象。能夠是另一個函數。

該參數不能被重寫。函數

arg1, arg2, ...this

可選。

傳給綁定函數的參數。prototype

做爲默認實參傳遞給綁定函數。code

假設參數是一個列表,如今有2種參數,一個是bind的實參參數,一個新的綁定函數中傳遞的實參參數。bind()的參數在綁定函數的參數的前面。對象

用法:可使綁定函數有初始的默認參數。作用域

例子:get

function funa(){
    "use strict";
    console.log(arguments[0]);//33
    console.log(arguments[1]);//11
    
}
var o = {
    x:1
}
var funb = funa.bind(o,33);
funb(11);//輸出33  \n  11

兼容性:

支持bind()方法的瀏覽器有IE9+。

bind和call、apply的差異

bind是ES5新增方法,不會執行對應的函數(call或apply會自動執行對應的函數),而是返回對綁定函數的引用。

  • call、apply的區別:接受參數的方式不同。
  • bind:不當即執行。而apply、call 當即執行。

bind和構造函數

構造函數可使用bind(),而後再次建立實例。

bind()提供的 this值被忽略,提供的那些參數仍然會被前置到構造函數調用的前面。

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

Point.prototype.toString = function () {
    return this.x + ',' + this.y;
};

var p = new Point(1, 2);
p.toString(); // '1,2'

var YA = Point.bind(null, 0);

var axis = new YA(5);
axis.toString(); // '0,5'

axis instanceof Point; // true
axis instanceof YA; // true
new Point(17, 42) instanceof YA; // true

例子:

window.color = "red";
var o = { color: "blue" };

function sayColor() {
    console.log(this.color);
}
var objectSayColor = sayColor.bind(o);
objectSayColor(); //blue

bind()應用

改變對象的方法的this

目的:使對象的方法在不是這個對象使用時,this的指向依然是這個對象。

緣由:建立一個變量,指向爲對象的方法,獲得一個新函數。這個新函數中的this值已經再也不指向原對象了。

name = "hello";

var mo = {
    name:2010,
    getName:function(){
        console.log(this.moyu);
        
    }
};

mo.getName();//2010

var newMo = mo.getName;//在這種狀況下,"this"指向全局做用域window。


newMo();//hello

var nextMo = mo.getName.bind(mo);
nextMo();//2010

設置默認實參

bind()能夠將undefined做爲this指向,而後傳入默認實參。

用法:

fun.bind(undefined,33);

function list(){
   let res = Array.prototype.slice.call(arguments);
    console.log(res);
    
}

list(1,2,3);//[1,2,3]

let newList = list.bind(null,3);
newList();//[3]
newList(1);//[2,1]

配合 setTimeout

在默認狀況下,使用setTimeout(function,time); 時,函數的this關鍵字會指向window。

在原型上的方法中,this是實例對象。使用setTimeout,必須顯式的把實例對象綁定到它的函數中,不然this爲window對象。

function LateBloomer() {
    this.petalCount = Math.ceil(Math.random() * 12) + 1;
}


LateBloomer.prototype.declare = function() {
    console.log('I am a beautiful flower with ' +  this.petalCount + ' petals!');
};

LateBloomer.prototype.bloom = function() {
    console.log(this);//LateBloomer {patalCount:4};
    
    setTimeout(this.declare.bind(this), 1000);
    //zxy456:2個this都是指向LateBloomer.
    //若是不加bind,setTimeout調用的函數的this爲window。declare中的this變爲window了。
};


var flower = new LateBloomer();

flower.bloom();  // 一秒鐘後, 調用'declare'方法

ES3版本的bind()方法

zyx456思路:將bind()和函數的參數合併。而後運行apply便可。

if (!Function.prototype.bind) {
    Function.prototype.bind = function (o) {
        var self = this, arg = Array.prototype.slice.call(arguments, 1);

        var fbind = function () {
            var arr = [...arg, ...arguments];
            // 如今將self做爲o的方法來調用,傳入這些實參
            return self.apply(o, arr);
        };
        fbind.prototype = this.prototype;//用於bind構造函數。
        return fbind;
    };
}
相關文章
相關標籤/搜索