this的指向规则

1.this的默认绑定规则
  • 全局环境中this指向了window
  • 函数的独立调用中指向了window
  • 被嵌套的函数独立调用的时候,指向了window
  • IIFE 独立函数中this指向了window
  • 闭包 this默认指向了window
// 全局环境中
console.log(this === window) // true

// 一般的函数独立调用
function test(){
  console.log(this === window)
}
test(); // true, 其他写法: window.test();  this.test();

// 嵌套函数的独立调用
var a = 2;
var obj = {
  a: 2;
  foo: function() {
    function test() {
     	console.log(this) // window 这里指向了window,因为这里的test()是独立调用,独立调用的函数的this指向window
    }
    test()
  }
}

// 立即执行函数(立即执行函数this全部指向window --- 非严格模式下):
1.(function test() {   // 官方推荐标准写法
  ...
}())
2.(function test() {
  ...
})()

在这里看学习时候有一个判断

Console.log({} === {}) // false

这里返回了false是因为两个空对象{}的指针并不相等, 所以不允许用{}去判断一个对象是否为空并且作为条件判断语句;

2.this的隐式绑定规则

一般指的是谁直接调用指向谁, 在函数中, 一般函数执行this的指向才有意义(预编译), 函数不执行this的指向没有意义;每一个函数执行都有个this的生成;

var a = 2;
function foo() {
  console.log(this)
}
var obj = {
  a: 2;
  foo:foo
}
obj.foo() // 指向了直接调用对象obj
额外补充函数声明,函数执行以及函数立即执行的区别:
function test() { // 这一部分为函数声明
  ....
}
test(); // 这里是上面的函数执行
3.隐式丢失

隐式丢失指的是被隐式绑定的函数丢失了绑定对象, 从而默认绑定到了window

  • 函数别名
  • 参数传递
  • 内置函数
// 函数别名
var a = 2;
function foo() {
  console.log(this)
}
var obj = {
  a: 2;
  foo:foo
}
var bar = obj.foo

// 参数传递
var a = 2;
function foo() {
  console.log(this)
}
var obj = {
  a: 2;
  foo:foo
}
function bar(fn) {
  fn()
}
bar(obj.foo) 

// 内置函数
var a = 2;
function foo() {
  console.log(this)
}
var obj = {
  a: 2;
  foo:foo
}
setTimeout(obj.foo, 1000) // setTimeout()函数的第一个参数的回调中的this指向了window

// 函数的间接调用var a = 2;
function foo() {
  console.log(this)
}
var obj = {
  a: 2;
  foo:foo
}
var p = {a: 4;}
(p.foo = obj.foo) // 这是立即调用函数,将obj.foo赋值给了p.foo,相当于p的foo函数立即调用
4.显式绑定

通过call(), apply(),bind()把对象绑定到this上

var a = 2;
var obj = {
  a: 1;
}
function foo() {
  console.log(this) 
}
foo(); // 指向了window
1. foo.call(obj)  // 以下指向了obj
2. foo.apply(obj)
3. var fn = foo.bind(obj)
			 fn();
5.new的绑定

如果是new关键字来执行函数,相当于构造函数实例化了对象,那么内部的this指向了实例化对象

 1.function foo() {
    console.log(this)
    return;
  }
  var fn = new foo(); 
	console.log(fn) // fn
2. function foo() {
    console.log(this)
  // 使用 return 那么实例化的对象是当前返回的对象 
    return {
      a: 'name'
    }
  }
  var fn = new foo();
		console.log(fn)  // {a: 'name'}
3. var person = {
    fav: function() {
      return this;
    }
  }
var p = new person.fav()
console.log(p.constructor === person.fav) // true 实例化的对象中constructor指向当前构造函数