// 三者的第一个参数都是this需要指向的对象
// 但在后续的参数上只有apply是接收一个数组,call和bind用逗号分开
// call和apply直接调用,返回的是一个值
// 而bind不直接调用,返回的是一个函数形式,执行:foo.bind(obj)()
Function.prototype._call = function(context = window, args) {
context.fn = this;
const res = context.fn(...args);
delete context.fn;
return res;
}
Function.prototype._apply = function(context = window, args) {
context.fn = this;
const res = context.fn(args);
delete context.fn;
return res;
}
//真数组 =》类数组转换
// var arr = [1,3,5];
// var obj = {};
// [].push.apply(obj,arr); // { 0:1, 1:3 , 2:5 , length:3 }
// 类数组 ==> 真数组转换
// 系统自带类数组对象
// var divs = document.querySelectorAll('div');
// 自定义类数组对象
// var obj = {0:'lqs' , 1:18 , length:2};
// var arr = []; // 真数组
// 在高级的浏览器中使用如下的方法是可以实现类数组对象转换为真数组,但是在 IE8 及其以下是不行的
// [].push.apply(arr,divs);
// [].push.apply(arr,obj);
// 为了兼容 IE8 及其以下的浏览器,需要使用数组的 slice 方法
// 数组的 slice 方法不传递参数的时候是将数组中的元素依次遍历然后放到一个 新的数组 中原样返回
// var arr2 = [].slice.call(obj);
// 一切以数组为输入,并以数组为输出的API都可用来做数组转换
// const arrayLike = {0: 3,1: 4,2: 5,length: 3}
// Array.prototype.slice.call(arrayLike)
// Array.apply(null, arrayLike)
// Array.prototype.concat.apply([], arrayLike)
// Array.prototype.slice.call(arrayLike)
// Array.prototype.map.call(arrayLike, x => x)
// Array.prototype.filter.call(arrayLike, x => 1)
// ES6:Array.from()、... 扩展运算符
// // Array.from();方法用于将类数组对象和可遍历(Iterator)对象转换为真数组
// var obj = {0:'lqs' , 1:18 , length:2};
// var arr = Array.from(obj) // ['lqs',18]
// ... 扩展运算符
// 适用于 iterable 对象 [...doucmnet.querySelector('div')]
// 但在{length:3}这种情况下会抛出异常
// Uncaught TypeError: object is not iterable (cannot read property Symperty Symbol(Symbol.iterator))[...{length:3}]
// 总结:
// 以上方法中靠谱的数组转换方法
// Array.from(arrayLike)
// Array.apply(null, arrayLike)
// Array.prototype.concat.apply([], arrayLike)
//返回一个绑定了上下文的新函数,不是立即执行的
Function.prototype._bind = function(context = window, ...args) {
var fn = this;
return function(...innerArgs) {
return fn.apply(context, [...args, ...innerArgs]);
}
}
// var value = 2;
// var foo = {
// value: 1
// };
// function bar(name, age) {
// return {
// value: this.value,
// name: name,
// age: age
// }
// };
// bar.call(foo, "Jack", 20); // 直接执行了函数
// // {value: 1, name: "Jack", age: 20}
// var bindFoo1 = bar.bind(foo, "Jack", 20); // 返回一个函数
// bindFoo1();
// // {value: 1, name: "Jack", age: 20}
// var bindFoo2 = bar.bind(foo, "Jack"); // 返回一个函数
// bindFoo2(20);
// // {value: 1, name: "Jack", age: 20}
call apply 和bind 实现以及区别
最新推荐文章于 2024-04-19 11:37:34 发布