调用位置
函数在代码中被调用的位置
查找方法:
分析调用栈(调用位置就是当前正在执行的函数的前一个调用中)
1 | function baz() { |
使用开发者工具的到调用栈:
设置断点或者插入debugger;
语句,运行时调试器会在那个位置暂停,同时展示当前位置的函数调用列表,这就是调用栈。找到栈中的第二个元素,这就是真正的调用位置。
绑定规则
默认绑定
- 独立函数调用,把默认绑定看作是无法应用其他规则时的默认规则,此时this指向全局对象
- 严格模式下,this会绑定到undefined。只有函数运行在非严格模式下,默认绑定才能绑定到全局对象。在严格模式下调用函数不影响默认绑定
1 | function foo() { // 运行在严格模式下,this会绑定到undefined |
隐式绑定
当函数引用有上下文对象时,隐式绑定规则会把函数中的this绑定到这个上下文对象。
对象属性引用链中只有上一层或者说最后一层在调用中起作用。
1 | function foo() { |
特定情况下,被隐式绑定的函数特定情况下会丢失绑定对象,导致默认绑定,把this绑定到全局对象或undefined。
1 | // 虽然bar是obj.foo的一个引用,但是实际上,它引用的是foo函数本身。 |
参数传递就是一种隐式赋值,传入函数时也会被隐式赋值。回调函数丢失this绑定是非常常见的。
1 | function foo() { |
显式绑定
call(..) 或者 apply(..)方法。第一个参数是一个对象,在调用函数时将这个对象绑定到this。因为直接指定this的绑定对象,称之为显示绑定。
1 | function foo() { |
显示绑定无法解决丢失绑定问题。
解决办法:
- 1.硬绑定
- 2.API调用的“上下文”
new 绑定
使用new调用函数,或者说发生构造函数调用时,执行操作:
- 创建(或者说构造)一个新对象
- 这个新对象被执行[[Prototype]]连接
- 这个新对象会绑定到函数调用的this
- 如果函数没有返回其他对象,new表达式中的函数调用会自动返回这个新对象
1 | function foo(a) { |