在JavaScript里,call(),apply(),bind()都是Function内置的三个方法, 它们的作用都是显示的绑定this的指向,三个方法的第一个参数都是this指向的对象,也就是函数在运行时执行的上下文。
当我们定义一个新的对象,需要使用其他对象的方法的时候,我们不需要重新开发重复的方法逻辑,借助apply,apply,bind三个方法可以实现对这些的方法的调用。
我们定义三者的概念:
apply:调用一个对象(obj)的方法(func),并使用新的对象(thisArg)代替该对象,参数是数组
obj.func.apply(thisArg, [argsArray])
call:调用一个对象(obj)的方法(func),并使用新的对象(thisArg)代替该对象,参数是列表
obj.func.call(thisArg, arg1, arg2, ...)
bind:bind()方法创建一个新的函数,在bind()被调用时,这个新函数的this被bind的第一个参数指定,其余的参数将作为新函数的参数供调用时使用,第一个thisArg在setTimeout中创建一个函数时传递的原始值都会转化成object,如果bind参数列表为空,thisArg赋值当前当前运行环境this
function.bind(thisArg[,arg1[,arg2[, ...]]])
特点:
常见的一些应用:
我们创建arr和other两个数组,当我们需要合并两个数组的时候,可以使用concat方法进行操作,但是concat需要创建新的数组对象,我们可以借助apply方法不需要创建新的对象,不需要遍历数组,也可以实现需求:
let arr = [2,3,4,5,6];
let other = [10,89];
arr.push.apply(arr, other); // or Array.prototype.apply(arr, other)
console.log(arr); // [2, 3, 4, 5, 6, 10, 89]
我们借助了apply方法,push方法在调用的时候,this指向的是arr对象,这里的参数列表other,我们将other数组合并到arr数组对象上。
下面的是两种比较常见的写法,其实是一样的
function Animal(name) {
this.name = name;
this.run = function() {
console.log(`${this.name} is running!`)
}
}
function Cat(name) {
Animal.call(this, name);
}
let tom = new Cat("TOM");
tom.run(); // TOM is running!
this.name = 'global';
let cacheFun = {
name : 'cache',
getCacheName : function() {
console.log("Name: ",this.name)
}
}
cacheFun.getCacheName(); // Name is cache
let cacheName = cacheFun.getCacheName;
cacheName(); // Name: global
在创建绑定函数的实例中,我们分析一下一部分调用过程:
我们需要借助bind方法,在函数调用的时候,绑定this的执行到cacheFun对象上:
let cacheNameByBind = cacheName.bind(cacheFun);
cacheNameByBind(); // Name is cache
Function.prototype.applyFun = function(content) {
content = content || window;
content.fun = this;
var argsArr = arguments[1];
if(!argsArr) {
return content.fun();
}
if(!Array.isArray(argsArr)) {
throw Error("参数列表必须是数组的格式!")
}else {
var result ;
var len = argsArr.length;
for(var i=0;i < len; i++) {
result = content.fun(argsArr[i]);
}
delete content.fun;
return result;
}
}
// 测试
var arr = [1,5];
var other = [34,5,5];
Array.prototype.push.applyFun(arr, other);
console.log(arr) // [1, 5, 34, 5, 5]
Function.prototype.callFun = function(content) {
content = content || window;
content.fun = this;
var args = [];
for(var i=1;i<arguments.length;i++) {
args.push(arguments[i]);
}
eval(`content.fun(${args})`); //字符串拼接
delete content.fun;
}
let arr = [1,2,3]
Array.prototype.push.callFun(arr, 4,5,6,6);
console.log(arr); // [1,2,3,4,5,6,6]
基础版
Function.prototype.bindFun = function(content) {
let that = this;
return function() {
return that.apply(content)
}
}
let Person = {
getName : function() {
console.log(`Name is ${this.name}`)
}
}
let Liming = {
name: 'ming'
}
let getName = Person.getName;
let getNmaeByming = getName.bindFun(Liming);
getNmaeByming(); // Name is ming
最终版本,处理通过new创建绑定是的this绑定,将that对象传入闭包缓存
Function.prototype.bindFun = function(content) {
if(typeof this !== 'function') {
return;
}
var that = this;
var args = Array.prototype.slice.call(arguments, 1);
var _bindFun = function() {
var _content = this instanceof that ? this: content;
var _args = [].slice.call(arguments, 0);
that.apply(_content , args.concat(_args));
}
var BindFun = function() {};
if(this.prototype) {
BindFun.prototype = this.prototype;
_bindFun.prototype = new BindFun();
}
return _bindFun;
}
// 测试
function Point(x, y) {
this.x = x;
this.y = y;
}
Point.prototype.toString = function() {
return this.x + ',' + this.y;
};
var emptyObj = {};
var YAxisPoint = Point.bindFun(emptyObj, 0);
var axisPoint = new YAxisPoint(5);
var str = axisPoint.toString();
console.log(str) // '0,5'
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。