脚本宝典收集整理的这篇文章主要介绍了详解call bind apply - 区别/使用场景/es6实现/es3实现,脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。
call,apply,bind的区别
- apply接收数组 func.apply(obj, [arus])
- call一连串参数 func.call(obj, param1, param2....)
- bind返回一个函数 func.bind(obj,param...)(parms...)
call,apply,bind的使用场景
-
类数组:(例如通过document.getelementsbytagname获取的元素、含有length属性的对象)具有length属性,并且可以通过0、1、2…下标来访问其中的元素,但是没有Array中的push、pop等方法。
注意:但是这个不适用于IE6~8,会报错,只能使用循环来解决
// 类数组
let trueArr = Array.PRototyPE.slice.call(arrayLike)
// 含有length属性的对象
let obj4 = {
0: 1,
1: 'thomas',
2: 13,
length: 3 // 一定要有length属性
};
console.LOG(Array.prototype.slice.call(obj4)); // [1, "thomas", 13]
-
求数组中的最大和最小值
注意:边界问题,临界值大概在 [ 参数个数限制在65536]
let arr = [1,2,3,89,46]
let max = Math.max.apply(null,arr)//89
let min = Math.min.apply(null,arr)//1
-
数组追加
数组方法contact比较:contact返回新数组,不修改原数组
let arr1 = [1,2,3]
let arr2 = [4,5,6]
let total = [].push.apply(arr1, arr2) //6
-
利用call和apply做继承
function Person(name,age){
// 这里的this都指向实例
this.name = name
this.age = age
this.sayAge = function(){
console.log(this.age)
}
}
function Female(){
Person.apply(this,arguments)//将父元素所有方法在这里执行一遍就继承了
}
let dot = new Female('Dot',2)
-
判断变量类型
function isArray(obj){
return Object.prototype.toString.call(obj) == '[object Array]'
}
isArray([]) // true
isArray('dot') // false
-
其他:使用 log 代理 console.log
function log(){
console.log.apply(console, arguments);
}
// 当然也有更方便的 let log = console.log()
bind 实现
-
特点:
- 注意:bind这个方法在IE6~8下不兼容
// 使用apply和call来实现this指向问题
Function.prototype.bind2 = function (context) {
if (typeof this !== "function") {
throw new Error("what is trying to be bound is not callable");
}
var self = this;
// 获得bind的参数从第二个参数到最后一个参数
var args = Array.prototype.slice.call(arguments, 1);
var fNOP = function () {};
var fBound = function () {
// 指bind返回的函数传入的参数
var bindArgs = Array.prototype.slice.call(arguments);
// 当作为构造函数时,this 指向实例,此时结果为 true,将绑定函数的 this 指向该实例,可以让实例获得来自绑定函数的值
// 以上面的是 demo 为例,如果改成 `this instanceof fBound ? null : context`,实例只是一个空对象,将 null 改成 this ,实例会具有 habIT 属性
// 当作为普通函数时,this 指向 window,此时结果为 false,将绑定函数的 this 指向 context
// new bind返回的函数,this失效,但传入的参数生效
return self.apply(this instanceof fNOP ? this : context, args.concat(bindArgs));
}
// fBound.prototype = this.prototype;
// 保证继承,原型链,让 fBound 构造的实例能够继承绑定函数的原型中的值,下面两行代码等同于Object.creater() fbound.prototype = Object.create(this.prototype);
// 我们直接修改 fBound.prototype 的时候,也会直接修改绑定函数的 prototype。这个时候,我们可以通过一个空函数来进行中转
fNOP.prototype = this.prototype;
fBound.prototype = new fNOP();
return fBound;
}
// es6实现
Function.prototype.bind = function(context) {
if(typeof this !== "function"){
throw new TypeError("not a function");
}
let self = this;
let args = [...arguments].slice(1);
function Fn() {};
Fn.prototype = this.prototype;
let bound = function() {
let res = [...args, ...arguments]; //bind传递的参数和函数调用时传递的参数拼接
context = this instanceof Fn ? this : context || this;
return self.apply(context, res);
}
//原型链
bound.prototype = new Fn();
return bound;
}
call 实现