1.this引用的是函数执行的环境对象,this在代码执行过程中可能引用不同的对象,他实际最终指向的是那个调用它的对象。
function a(){
var user = "shisha";
console.log(this.user); //undefined
console.log(this); //Window}
a();
2.call,apply,bind
作用:改变this的指向
区别:它们的区别主要是在于方法的实现形式和参数传递上的不同
①:函数.call(在其中运行函数的作用域,传递给函数的参数(必须一一列举出来))
var foo={
value:1
}
function bar(){
console.log(this.value);
}
bar.call(foo)
js模拟实现call的方法,分为三步:
第一步:模拟添加属性方法
foo.fn=bar
第二步:调用方法
foo.fn()
第三步:删除方法
delete foo.fn
// es3模拟实现call
Function.prototype.callOne=function(context){
//如果context是null,作用域是window
context=context||window;
//添加方法
context.fn=this;
var args=[];
//如果直接把arguments[i]push给args,eval会先对args.toString,arguments[i]就会变成一个没有声明,会出错的变量
for(var i=1;i<arguments.length;i++){
args.push('arguments.push['+i+']');
}
var result=eval('context.fn('+args+')');
delete context.fn;
return result;
}
var foo={
value:1
}
function bar(){
console.log(this.value);
}
bar.callOne(foo)
②:函数.apply(在其中运行函数的作用域,参数数组(可以是Array实例也可以是arguments对象))
call和apply基本相同就是参数不同
// es3模拟实现apply
Function.prototype.callTwo=function(context,arr){
context=context||window;
arr=arr||[];
context.fn=this;
var args=[];
for(var i=0;i<arr.length;i++){
args.push('arr.push['+i+']');
}
var result=eval('context.fn('+args+')');
delete context.fn;
return result;
}
var foo={
value:1
}
function bar(){
console.log(this.value);
}
bar.callTwo(foo)
③:var ss=函数.bind(在其中运行函数的作用域,arg1,arg2,....)
https://blog.csdn.net/lisummit/article/details/80561786
b.bind(a)它是返回了一个被修饰的函数,bind() 之后函数并没有执行, 可以传给其他函数, 在某个适当的时机再调用,使用更加灵活。
// es3模拟实现bind
Function.prototype.bindOne=function(context){
if(typeof this!=='function'){
throw new Error('bound is not callable')
}
//留住this
var self=this;
//arguments转数组,并从index=1截取
var args=Array.prototype.slice.call(arguments,1);
var fNop=function (){};
var fBound=function (){
var boundArgs=Array.prototype.slice.call(arguments);
return self.apply(this instanceof fNop?this:context,args.concat(boundArgs))
}
//原型链继承
fNop.prototype=this.prototype;
fBound.prototype=new fNop();
return fBound;
}
var foo={
value:1
}
function bar(){
console.log(this.value);
}
var a=bar.bindOne(foo)
a();