var name = "lucy";
var obj = {
name: "martin",
say: function () {
console.log(this.name);
}
};
//1
obj.say(); // martin,this 指向 obj 对象
//2
setTimeout(obj.say,0); // lucy,this 指向 window 对象
//3
setTimeout(obj.say.bind(obj),0); //martin,this指向obj对象
function fn(...args){
console.log(this,args);
}
let obj = {
myname:"张三"
}
fn.apply(obj,[1,2]); // this会变成传入的obj,传入的参数必须是一个数组;
fn(1,2) // this指向window
function fn(...args){
console.log(this,args);
}
let obj = {
myname:"张三"
}
fn.call(obj,1,2); // this会变成传入的obj,传入的参数必须是一个数组;
fn(1,2) // this指向window
function fn(...args){
console.log(this,args);
}
let obj = {
myname:"张三"
}
const bindFn = fn.bind(obj); // this 也会变成传入的obj ,bind不是立即执行需要执行一次
bindFn(1,2) // this指向obj
fn(1,2) // this指向window
总结:三者的区别
这里可以结合函数柯里化-CSDN博客⭐这篇文章去理解他们的应用。
Function.prototype.myApply = function(context){
//判断调用对象是否为函数
if(typeof this!="function"){
throw new TypeError("Error");
}
let result =null;
context = context||window;
context.fn = this;
if(arguments[1]){
result = contetx.fn(...arguments[1]);
}else{
result = context.fn()
}
delete context.fn;
return result;
}
Function.prototype.myCall = function(context){
//判断调用对象是否为函数
if(typeof this!="function"){
throw new TypeError("Error");
}
let args = [...arguments].slice(1),result =null;
context = context||window;
context.fn = this;
result = contetx.fn(...args);
delete context.fn;
return result;
}
Function.prototype.myBind = function(context){
//判断调用对象是否为函数
if(typeof this!="function"){
throw new TypeError("Error");
}
let args = [...arguments].slice(1),fn = this;
return function Fn(){
return fn.apply(
this instanceof Fn ? this : context,
args.concat(...arguments)
)
};
}
修改this指向、动态传参
// 方式一:只在bind中传递函数参数
fn.bind(obj,1,2)()
// 方式二:在bind中传递函数参数,也在返回函数中传递参数
fn.bind(obj,1)(2)
参考文献
函数 -- JavaScript 标准参考教程(alpha)