调用位置:函数在代码中调用的位置,而不是声明的位置。
调用栈:为了到达当前执行位置的所有调用的函数。
例子:
function baz(){ //当前调用栈为baz //调用位置是全局作用域 console.log("baz"); bar(); //bar的调用位置 } function bar(){ //当前调用栈为bar->baz //调用位置是baz console.log("bar"); foo(); //foo调用位置 } function foo(){ //当前调用栈为foo->bar->baz //调用位置是bar console.log("foo"); }
调用位置则是调用栈的第二个元素,可以使用调试器找出调用栈。
函数执行过程中如何使用调用位置决定this的绑定对象。
this绑定有四种规则:
1.默认绑定:this指向全局对象,可以看做无法应用其他规则时的默认规则。
function foo(){ console.log(this.a); } var a = 2; foo() // 2
通过分析调用位置,发现foo()是直接使用不带任何修饰的函数进行调用的。
2.隐式绑定:调用位置是否有上下文。
function foo(){ console.log(this.a); } var obj = { a:2, foo:foo }; obj.foo() //2
调用位置会使用obj上下文来引用函数。注意,当使用回调函数时,因为函数作为参数传入时,实际上是一个隐式赋值操作,如下:
function foo(){ console.log(this.a) } function doFoo(fn){ //fn其实引用的是foo fn(); //调用位置 } var obj ={ a:2, foo:foo } var a = "global"; doFoo(obj.foo); //"global"
3.显式绑定:即使用call,apply,bind等内置函数修改this的值。
var obj ={ a:2 } function d (){ console.log(this.a) } d.call(obj); //2
显式绑定中有一种硬绑定:用于为了保证this不缺失,如下:
var obj ={ a:2 } var abc = function(){ d.call(obj); //d函数的this一直指向了obj } function d (){ console.log(this.a) } abc(); //2
4:new绑定。(Js中的new与其他语言完全不同)
new操作有以下四个步骤:
1.创建一个全新的对象。
2.这个对象会被执行原型链接。
3.这个对象会绑定到函数调用的this.
4.如果函数没有返回其他对象,则new表达式中的函数调用自动返回这个对象。
function foo(){ this.a =2; } var baz = new foo(); console.log(baz.a); //2
最后是优先级:
new>显示>隐式>默认。
具体例子可参考书P91~P。。。