call apply 和bind 实现以及区别

// 三者的第一个参数都是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}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值