【JS脚丫系列】
- 【JS脚丫系列】一道经典的this面试题(复杂度两颗星)
- 【JS脚丫系列】严格模式"use strict";
- 【JS脚丫系列】JS基础知识脉络 By 吃码小妖
- 【JS脚丫系列】重温闭包
- 【JS脚丫系列】重温bind
概念
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);
//吃码小妖:2个this都是指向LateBloomer.
//如果不加bind,setTimeout调用的函数的this为window。declare中的this变为window了。
};
var flower = new LateBloomer();
flower.bloom(); // 一秒钟后, 调用'declare'方法
ES3版本的bind()方法
吃码小妖思路:将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;
};
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。