JS脚印重温bind

8次阅读

共计 2612 个字符,预计需要花费 7 分钟才能阅读完成。

概念

bind() 方法会返回一个新函数(称为绑定函数),绑定函数与原函数(使用 bind() 的函数)具有相同的函数体,但是绑定函数有新的 this 值和参数。

说白了,bind() 就是创建一个有着新 this 和实参的函数。

语法:

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

thisArg

绑定函数中 this 的指向。可以是 null,undefined,{},或其他任意对象。可以是另外一个函数。

该参数不能被重写。

arg1, arg2, …

可选。

传给绑定函数的参数。

作为默认实参传递给绑定函数。

假设参数是一个列表,现在有 2 种参数,一个是 bind 的实参参数,一个新的绑定函数中传递的实参参数。bind() 的参数在绑定函数的参数的前面。

用法:可以使绑定函数有初始的默认参数。

例子:

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;
    };
}

正文完
 0