/*
* 目标:
* 1. call、 apply、 bind作用及用法
* 2. call、 apply、 bind三个方法有什么区别
* */
console.dir(Function.prototype);
// 1. 事件函数中的 this 是绑定当前事件的元素
// 2. 自执行函数中的 this 指向 window
// 3. 定时器回调函数中的 this 指向 window
// 4. 全局作用域中的 this 是 window
// 5. 方法调用时,看方法名前面有没有点,有点的话,点前面是谁方法中的 this 就是谁,如果没有点,方法中的 this 就是 window
// 6. 箭头函数中的 this 指向声明时所在作用域中的 this
// 7. 构造函数中的 this 指向当前实例
// 8. call / apply / bind 用来修改 this 指向
function sum(a, b) {
console.log(this);
console.log(a, b);
return a + b;
}
var obj = {
id: '0511120117'
};
// sum(1, 2); // window
// 1. call()
// 作用: 修改函数中的 this 指向,并且把修改 this 后的函数执行
// 语法:函数名.call(ctx, 实参1, 实参2.....)
// 参数:ctx 就是用来替换函数中this的对象,从第二个参数起,都是传递给函数的实参
// sum.call(obj, 2, 3); // call 之后,sum 中的 this 就变成了 obj
// 模拟一个 call 方法
~ function () {
function call(context) {
context = context || window;
let args = [],
result;
for (let i = 1; i < arguments.length; i++) {
args.push(arguments[i]);
}
context.$fn = this;
result = context.$fn(...args);
delete context.$fn;
return result;
}
Function.prototype.call = call;
}();
// 基于 ES6 语法重构
~function () {
/*生成随机函数名:时间戳的方式*/
function queryRandomName () {
let time = new Date().getTime();
return '$zhufeng' + time;
}
// 模拟 CALL 方法改变函数中的 THIS
function changeThis(context = window,...arg){
let _this = this,
result = null,
ran = queryRandomName();
context[ran] = _this;
result = context[ran](...arg);
delete context[ran];
return result;
};
Function.prototype.changeThis = changeThis;
}();
// 用 call 指定 undefined 和 null 作为 this 无效;
// sum.call(undefined, 3, 4);
// sum.call(null, 1, 3);
// sum.call();
// 2. apply()
// apply 方法和 call 方法作用一样,修改函数中的 this,并且让这个修改 this 之后的函数执行;
// 但是传参方式不同;call 方法是一个一个的传递实参给 sum 的,apply 是把实参都放到一个数组中,数组项是传递给 sum 的实参;
// 模拟一个 apply 方法
~function(){
/*生成随机函数名:时间戳的方式*/
function queryRandomName () {
let time = new Date().getTime();
return '$zhufeng' + time;
}
function changeThis (context = window, arg = []) {
let _this = this,
result = null,
ran = queryRandomName();
context[ran] = _this;
result = context[ran](...arg);
delete context[ran];
return result;
};
Function.prototype.changeThis = changeThis;
}();
let res = fn.changeThis(obj,[100,200]);
// sum.apply(obj, [11, 12]);
// var ary = [1, 2, 3, 4, 5];
// sum.apply(obj, ary);
// 3. bind() 方法:
// 作用:修改函数中的 this,返回一个修改 this 后的新函数;不会让函数执行。
let sum2 = sum.bind(obj, 1, 2); // 传参的时候和 call 一样,需要一个一个的传
console.log(sum2);
console.log(sum === sum2); // false 因为 sum2 是一个新函数
sum2(); // 修改 this 后,需要自己执行一次这个函数
// call 和 apply 是修改 this 并且让函数执行,call 是一个一个的传参,apply 传递一个数组
// bind 是只修改 this 返回修改 this 后的新函数,并不会让函数执行;
一、模拟call方法:图
二、阿里的一道面试题
// 阿里的面试题
function fn1(){console.log(1);}
function fn2(){console.log(2);}
fn1.call(fn2);
fn1.call.call(fn2);
Function.prototype.call(fn1);
Function.prototype.call.call(fn1);