调用位置
调用位置也就是函数调用的位置,想找调用位置得从调用栈下手。
什么是调用栈? 调用栈可以理解为是函数的调用链。
如:
function a() {
//此时调用栈为 a
//因此此时的调用位置是 全局作用域
console.log("我是a函数");
b();
}
function b(){
//此时调用栈为 a -> b
//因此调用位置为 a
console.log("我是b函数");
c();
}
function c(){
//此时调用栈为 a -> b -> c
//因此调用位置为 b
console.log("我是c函数");
}
绑定规则
默认绑定
默认绑定即其他绑定方式用不了时,使用的绑定方式,但是在严格模式下,不能将全局对象用于默认绑定
隐式绑定
如果当前有上下文对象,或者被某个对象拥有,包含,严格来说,这个函数不属于对象,所以this会绑定这个上下文对象。但是对象引用链只在上一层有效,如:
function baz(){
console.log(this.name);
}
let obj1 = {
name: '张三',
baz: baz
}
let obj2 = {
name: '李四',
baz: baz
}
obj1.obj2.baz();//李四
例:
function baz(){
console.log(this.a);
}
var a = "我是全局";
let obj = {
a: "我属于obj",
baz: baz
}
var fun = obj.baz
fun() //我是全局
上面的情况,fun实际上是直接调用baz函数引用,所以this应该绑定在全局环境中而不是obj对象上下文。
函数的传参其实也是传递引用,如:
function a(){
console.log(this.name)
}
let obj = {
a:a,
name: '我的名字'
}
function fun(fn){
fn(); //此处传递过来的参数为a本身引用,所以this应该是全局
}
var name = "全局名称"
fun(obj.a); //全局名称
```0
### 显示绑定
JavaScript提供了两种显示绑定的方式:call(),apply(),比如:
```javascript
function baz(){
console.log(this.a)
}
var a = 100
var obj = {
a: 200
}
baz() //100
baz.call(obj) //200
call把this强行绑定到obj上
硬绑定
创建一个函数,函数内部强行绑定我们像绑定的函数,此后无论怎么修改绑定都不会改变这个绑定,这就是硬绑定
new绑定
如:
function baz(a){
this.a = a
}
let foo = new baz(111)
foo.a //111
使用new来调用foo函数的时候,我们会构造一个新对象并把它绑定到foo(…)调用中的this上
优先级
显示绑定和隐式绑定对比:
function baz(){
console.log(this.a)
}
let obj1 = {
a: 100,
baz: baz
}
let obj2 = {
a: 200,
baz: baz
}
obj1.baz.call(obj2) //200
返回结果说明显式绑定的优先级大于隐式绑定
new绑定和隐式绑定对比:new绑定优先级更高
new绑定和显示绑定对比:new绑定优先级更高
如何判断this的绑定
- 首先看有没有使用new构造,如果new构造this就在绑定的对象上
- 再看有没有显式绑定,使用bind,call,apply绑定
- 有没有隐式绑定,对象上下文包含的情况
- 默认绑定,绑定在上一层函数上