当函数作为方法调用时,this指向函数的直接父对象,称为隐式绑定。

在隐式绑定规则中,认为 this 指向调用函数的人,并将指向函数的直接父对象。比如obj.foo()中foo函数里面的this指向obj,而obj1中的foo函数。obj2.foo() 指向 obj2。

var a = 10
function foo () {
  console.log(this.a);
}

var obj = {
a:
20,
foo: foo,
obj2: {
a:
30,
foo: foo
}
}

// exp1
foo() // 10

// exp2
obj.foo() // 20

// exp3
obj.obj2.foo() // 30

上面的代码也是对 foo 函数的调用。调用方法不同,结果不同。

‘exp1’中的foo直接被独立函数调用,所以,this指向Window,结果为10;‘exp2’中的调用方法是obj。foo(),foo函数的this指向上级调用对象obj;结果是 20。'exp3' 中 foo 函数的直接上级对象是 obj2,所以结果是 30。

 

 

隐式绑定丢失(常错题方式)

隐式绑定丢失意味着隐式绑定的函数丢失了它的绑定对象,所以默认绑定到Window。这种方法在我们的项目中很容易导致错误,但也很常见。

1、隐式绑定的函数被分配为没有 this 指向的变量。

在下面的代码中,obj下的foo值实际上是foo函数的地址信息,并不是真正的foo函数。当 obj.调用 foo() 时, this 的 this 隐式绑定到 obj。当 var fn=obj.foo 为 fn 分配一个函数时。相当于把foo函数的地址赋给fn。这时候fn没有和obj关联,所以这里fn()的运行环境就是全局环境,this指向Window,this的结果a 是 10。

var a = 10
var obj = {
  a: 20,
  foo: function () {
    console.log(this.a);
  }
}
function bar (fn) {
  fn()
}

bar(obj.foo) // 10

2、隐式绑定的函数作为参数传给函数,丢失了this点。

当一个隐式绑定的函数直接作为参数传递给另一个函数时,这个绑定会丢失,从而指向全局Window。obj.foo作为参数传给bar函数后,this.a的结果是10。这里bar(obj.foo)等价于var fn=obj.foo; bar(fn)。

var a = 10
var obj = {
  a: 20,
  foo: function () {
    console.log(this.a);
  }
}
function bar (fn) {
  fn()
}

bar(obj.foo) // 10

3、内置对象setTimeout和setInterval函数的隐式绑定丢失

4、箭头函数

 

 

 

练习题

function Foo() {
  getName = function () {
    console.log(1);
  };
  return this;
}
Foo.getName = function () {
  console.log(2);
};
Foo.prototype.getName = function () {
  console.log(3);
};
var getName = function () {
  console.log(4);
};
function getName() {
  console.log(5);
}
Foo.getName(); 
Foo().getName(); 
getName(); 
new Foo.getName(); 
new Foo().getName(); 
new new Foo().getName(); 
// 211233

第二题

var length = 10;
function fn() {
  console.log(this.length);
}
 
var obj = {
  length: 5,
  method: function(fn) {
    fn(); // 10
    arguments[0](); // 2
  }
};
 
obj.method(fn, 1);

第三题

function a(xx){
  this.x = xx;
  return this;
};
var x = a(5);
var y = a(6);

console.log(x.x);
console.log(y.x);
 

分析完代码的含义,我们来看输出结果。a函数传了一个参数5,那么this.x就被赋值为了5,函数a的this指向的是window,也就是window.x = 5。上面我们说过,这个函数返回的是this,也就是this指向的window,x = a(5)就相当于window.x = window,此时的x被赋值为了window。下面又执行了y = a(6),也就是说,x的值再次发生了改变,边为了6,y则被赋值为了window。console.log(x.x)就相当于console.log(6.x),输出的自然是undefined。console.log(y.x),输出的相当于是console.log(window.x),得到的值自然是6。最后输出的结果为 undefined 6。

posted on 2023-03-10 21:08  京鸿一瞥  阅读(39)  评论(0编辑  收藏  举报