this绑定的是一个对象,而调用位置决定了这个对象,通过调用栈就可以找到调用位置。
调用位置:函数在代码中被调用的位置(而不是声明的位置)。
调用栈:就是为了达到当前执行位置所调用的所有函数(其实包括普通的函数、全局作用域、对象)。this指向的就是函数当前位置与调用链中最近的上一层。
调用绑定的规则(情况)分作4种:
1、默认绑定~即函数直接在全局对象中调用,而不被其他函数调用,此时this绑定在全局对象。
严格模式的影响:函数*运行*在非strict模式下时,默认绑定才会绑带到全局对象,否则输出undefine,但在strict模式下调用是不会是不会影响默认绑定单位。
2、隐式绑定(方法调用模式)~即调用位置不是一个函数而是被某个对象拥有或者是包含(调用时前面带着一个点.表达式),此时this绑定在这个包含它的那个对象。但是一种情况下会出现隐式绑定的丢失。
function foo(){
console.log(this.a);
}
var obj1={
a:2,
foo:foo
};
var obj2={
a:42,
obj1:obj1
};
obj1.foo()//this指向obj
obj2.obj1.foo()//this指向obj,对象属性的引用链中只有离最近的那一个在调用位置中起作用。
隐式丢失:(因为在对象当中最为一个属性直接定义,还是现在对象外部先定义再引用,这个函数严格讲不属于这个对象)
function foo(){
console.log(this.a);
}
var obj={
a:2,
foo:foo
};
var bar=obj.foo;//关键位置*****
bar()//this指向全局
传递给一个回调函数时也存在隐式赋值,所以也会丢失。
调用回调函数的函数时,有些引擎会将this绑定到触发事件的dom元素上,譬如jquery中。。。
调用回调函数的函数时,有些引擎会将this绑定到触发事件的dom元素上,譬如jquery中。。。
关于对对象中一个方法获取一个对象的属性的值的问题
//情况一:
var a = {
t:3,
aa: function(){
alert(this.t);
}
};
a.aa() //3
//情况二:去调this后
var a = {
t:3,
aa: function(){
alert(t);
}
};
a.aa() //找不到t
原因:把变量的查找和属性的查找混起来了。
情况一:this指向的就是代调用该函数(aa)的对象,即a,而a就是有t这个属性的所以获取到了。
情况二:没有带this,单纯的就是根据作用域链来查找一个变量。那么由内到外来分析作用域:
-
函数本身的参数,无
-
函数内部定义的局部变量,无
-
函数所在作用域下(全局作用域)下是否有定义t变量,也无
3、显示绑定~即使用call、apply、bind进行绑定。
但是依然解决不了隐式丢失的问题。
为了解决隐式丢失可以:
(1)硬绑定,即给obj.foo外部套上一个包裹函数,然后在再赋给变量bar,执行bar()时就不会丢失。
(2)API中调用的上下文,就是一些内置函数内部采用bind方法进行绑定,eg:
[1,2,3].forEach(foo,obj);
4、new绑定~使用new操作符调用的函数,和类中的构造函数并不同,其实就是一个简单的函数。通过new调用创造了一个新的对象,此时新对象会被绑定到函数调用的this。
规则优先级:
new>硬绑定>隐式>默认
例外情况:
(1)call、apply、bind传入null或者undefine,此时采用默认绑定。
(2)间接引用,采用默认
(3)软绑定
es6中加入了this词法,即箭头函数。使用词法作用域来替代了传统的this。()=>{},此时箭头函数的内部的this继承外层函数调用的this绑定。
注:箭头函数绑定的this无法修改。