this对象是在函数运行时候基于函数的执行环境(上下文)绑定的
- 方法调用模式
- 函数调用模式
- 改造器调用模式
- apply,call,bind调用模式
1.方法调用模式
函数有所属对象,也就是这个函数是myObject.打点声明的的时候this是这个对象的本身,不可以说永远this都是myObject.
当一个函数被保存在为对象的一个属性的时,我们称它为一个方法,当一个方法被调用时,this被绑定到该对象;
var myObject = {
value :0,//记得这里是逗号不是分号
increment :function(inc){
console.log(this.value);//this为myObject
}
}
myObject.increment();//0
2.函数调用模式
当函数并非一个对象的属性时,那么它被当做一个函数来调用,this被绑定到全局对象(因为这个时候foo这个函数的上下文是window绑定的,this就指向window);
// 当执行myObject.getVlue时候
var myObject = { value: 100 }//创建myObject对象
myObject.getVlue = function () {
console.log(this.value);//100 这里的this值为myObject对象
var foo = function () {
console.log(this);//window; 调用foo()他的对象winfdow,所以函数的上下文(this)为window
console.log(this.value);//undefined,window没有设置value的值
}
foo(); //函数上下文是window,所以这里的this是window,文是window
}
console.log(myObject.getVlue());//没有设置返回值return
这里的foo函数就相当于,方法中的函数:这个函数与方法中的this是不同的(作用链的关系),这里的foo函数可以是一些其他的函数
注意:这里有个很麻烦的东西就是myObject.getVlue()函数中的this与foo()函数中的this不同为了为了让他们相同怎么办呢?
来来:就是赋值呵呵myObject.getVlue()函数中的this赋值给一个变量(that)就可以了
var myObject = {value: 100}//创建myObject对象
myObject.getVlue = function(){
console.log(this.value);//100这里的this值为myObject对象
that = this;//关键吧myObject对象转给了that这个变量(因为foo函数的上下文为window,想在foo函数中用myobject对象就把myobject对象赋值出来)
var foo = function(){
console.log(this);//window; 调用foo()他的对象winfdow,所以函数的上下文(this)为window
console.log(that)//为myObject
console.log(this.value);//undefined,window没有设置value的值
console.log(that.value);//100
}
foo();//函数上下文是window,所以这里的this是window,文是window
}
console.log(myObject.getVlue());//没有设置返回值return
3.构造器中的this:值向新的函数
js中,我们通过new关键词来调用构造函数,此时this会绑定在该对象上
var someClass = function () {
this.value = 100;
}
someClass();
console.log(window.value);//100说明了这个时候的this还是指向全局对象
var myCreate = new someClass();//构造对象;
console.log(myCreate.value);//这里this值向了myCreate
集合以上3个点来搞下面的这个题
var name = "222";
var a = {
name: "111",
say: function () {
console.log(this.name);
}
}
var fun = a.say;
fun(); // 222
a.say(); // 111
var b = {
name: "333",
say: function (fun) {
fun();
}
}
b.say(a.say); // 222 //这里为什么是222 这里的this为什么不是呢?应为这里b.say(a.say)执行的是function(fun){}函数,难后函数里面再执行fun(),这里的fun()为全局的执行上下文
b.say = a.say;
b.say(); // 333
这个题目真的是难的,但也不难就是看引用他的时候函数的执行上下文是谁
1.fun = a.say :定义了一个变量fun指向了a.say中的一个函数,所以当执行fun()的时候,fun()的执行期上下文为window,而和a.say()中this的执行是不一样的
2.a.say()函数上下文为那么就是a了
3.为什么是222,这里可以理解为 形参数fun等与了实参a.say,那么fun()的执行期一样也就是window
4.b.say(),这里也要注意虽然答案很好得到,但是我们要知道是为什么?这里的赋值这是该变了一下引用地址,当我们顺的那个指针去找函数上下文的时候那么就是b了,其实也就是说虽然里面执行的函数是在对象a中的但是呢?我们通过b.say = a.say;已经把函数执行其改为了b了
例子
this其实就是执行上下文中(词法环境中的一部分),而这里obj.a中是在全局执行上下中所以this为windew
a = 1
obj = {
a: 3,
b: this.a,
c: function () {
console.log(this); //{a: 3, b: 1, c: ƒ}
return this;
}
}
console.log(obj.b) //1
console.log(obj.c()) //{a: 3, b: 1, c: ƒ}
4.apply和call调用以及bind绑定:指向绑定对象;
var name = '小王'
var age =17;
var obj={
name:'zqx',
age:20,
myFun:function(num1,num2){
console.log(this.name+"年龄"+this.age+"来自"+num1+"去往"+num2)
}
}
//obj.myFun();
//console.log(obj.age);//20
var db ={
naem:'德玛',
age:99
}
obj.myFun.call(db,'成都','上海'); // 德玛 年龄 99 来自 成都去往上海
obj.myFun.apply(db,['成都','上海']); // 德玛 年龄 99 来自 成都去往上海
obj.myFun.bind(db,'成都','上海')(); // 德玛 年龄 99 来自 成都去往上海
obj.myFun.bind(db,['成都','上海'])(); // 德玛 年龄 99 来自 成都, 上海去往 undefined
三者的差别
1.bind方法返回一个新的函数,你必须调用它才可以执行.
2.call的参数和bind一样第二第三第 n 个参数全都用逗号分隔,直接放到后面 obj.myFun.call(db,'成都', ... ,'string' ).
3. apply 的所有传的参数都必须放在一个数组里面传进去 obj.myFun.apply(db,['成都', ..., 'string' ])
当然,三者的参数不限定是 string 类型,允许是各种类型,包括函数 、 object 等等!
用途
bind:有的时候当你只是想定义不想执行的时候用bind(),比如React在JSX元素上定义事件的时候
call applp:在使用便需要立马调用的时候