this

  • 函数在调用时,js会默认给this绑定一个值
  • this的绑定和定义的位置(编写的位置)没有关系
  • this的绑定和调用方式以及调用的位置有关系
  • this是在运行时被绑定的
this的默认绑定
// 普通函数的独立调用
function foo(){
  console.log(this)
}

foo() // window

// 函数定义在obj中,但独立调用
var obj = {
  name: 'sb',
  bar: function() {
    console.log(this)
  }
}
obj.bar() // 指向obj

var other = obj.bar
other()// 指向window

// 高阶函数
function test(fn) {
  fn()
}
test(obj.bar) // 指向window

// 严格模式下,独立调用的函数this指向undefined
"use strict"
this的隐式绑定
function foo() {
  console.log(this)
}
var obj = {
  bar: foo
}
obj.bar() // obj

var obj1 = {
  name: 'obj1',
  foo: foo
}
var obj2 = {
  name: 'obj2',
  obj1: obj1
}
obj2.obj1.foo() // obj1
new绑定
function foo() {
  console.log(this)
  this.name = 'sb'
}
// 创建一个新的空对象
// 将构造函数内的this指向新对象
// 执行代码,打印this,赋值name属性
// 如果函数没有返回其他对象,表达式会返回这个新对象
new foo() // obj

function Person(name) {
  console.log(this) // Person
  this.name = name // Person{name: 'xx'}
}
var p = new Person('xx')
console.log(p)
显式绑定
var obj = {
  name: 'sb'
}
function foo() {
  console.log('foo', this)
}
foo.apply(obj) // obj
foo.call(obj) // obj

foo.call(123) // 会创建包装类,指向Number
foo.call('abc') // 会创建包装类,指向String
foo.call(undefined) // 默认指向window
foo.call(null) // 默认指向window
call/apply/bind
// call/apply/bind
function foo(name, age, height) {
  console.log('foo', this)
  console.log('参数', name, age, height)
}
// ()调用
foo('sb', 19, 183) // window, 'sb', 19, 183

// apply
// 第一个参数:绑定this
// 第二个参数:传入额外的实参,以数组的形式
foo.apply('apply', ['zs', 21, 168]) // string, 'zs', 21, 168

// call
// 第一个参数:绑定this
// 第二个参数:以参数列表的形式传递,会作为实参
foo.call('call', 'ls', 26, 188) // sting, 'ls', 26, 188

// bind
function foo() {
  console.log('foo', this)
}
var obj = {name: 'SB'}
// 调用foo时,总是绑定到obj身上,同时不希望obj对象身上有foo函数
var bar = foo.bind(obj)
bar() // 指向obj

// bind 的其他参数,
function foo(name, age, height, address) {
  console.log('foo', this)
  console.log(name, age, height, address)
}
var obj2 = {name: 'cs'}
var bar = foo.bind(obj2, 'xx', 19, 203)

//bind 时就给赋值
bar() // obj2 'xx', 19, 203

// 后续赋值向后叠加
bar('new yark') // obj2 'xx', 19, 203, 'new yark'
规则优先级
  1. 默认规则优先级规则最低
  2. 显式绑定优先级高于隐式绑定
  3. new绑定优先级高于隐式绑定
  4. new不可以和apply,call一起使用,但与bind可以一起使用,且高于bind
// apply
function foo() {
  console.log(this)
}
var obj = {foo: foo}

obj.foo() // obj
obj.foo.apply('abc') // 显式高于隐 指向String

// call
function foo() {
  console.log(this)
}
var obj = {name: 'xx', foo: foo}

obj.foo() // obj
obj.foo.call(123) // 指向number

// bind
function foo() {
  console.log(this)
}
var bar = foo.bind('aaa')
var obj2 = {
  name: 'sb'
  baz: bar
}

obj2.baz() // 指向string AAA

// new  绑定
var obj = {
  name: 'sb',
  foo: function(){
    console.log(this)
    console.log(this === obj)
  }
}
obj.foo() // obj, true
// new会创建新的空对象,并且把this指向新的空对象,由于函数内没返回其他对象,所以this指向新的空对象而不是obj
new obj.foo() // 新的空对象, false

// new的优先级高于bind
function foo() {
  console.log(this)
}
var bindFn = foo.bind('abc')
bindFn() // 指向String abc
new bindFn() // 空对象

// bind的优先级高于apply和call
function foo() {
  console.log(this)
}
var bindFn = foo.bind('aaa')
bindFn() // 指向String aaa
bindFn.apply('bbb') // aaa
bindFn.call('ccc') // aaa
this规则之外、忽略显式绑定
  1. 如果显式绑定,传入null或undefined,使用默认规则
function foo(){
  console.log(this)
}
foo.call('abc') // String abc
foo.call(null) // window
foo.apply(undefined) // window

// 严格模式下
"use strict"
function foo(){
  console.log(this)
}
foo.call('abc') // abc
foo.call(null) // null
foo.apply(undefined) // undefined
  1. 创建一个函数的间接引用,这种情况使用默认绑定规则
var obj1 = {
  name: 'obj1',
  foo: function() {
    console.log(this)
  }
}
var obj2 = {
  name: 'obj2'
};

// obj2.foo = obj1.foo
// obj2.foo() // obj2

//会被独立函数调用,this指向window
(obj2.foo = obj1.foo)() // window
箭头函数的this使用

● 不会绑定this,arguments等属性
● 不能作为构造函数来用(不能和new一起使用,会抛错)

var bar = () => {
  console.log(this)
}
// 
bar() // window, 不是本身的作用域内的this,是上层的this,也就是window

bar.apply('aaa') // window // 向上层查找,本身作用域内不会有this的

var obj = {
  name: 'xx',
  foo: function() {
    var bar = () => {
      console.log(this)
    }
    return bar
  }
}
var fn = obj.foo()
fn.apply('bbb') // 指向obj(apply给箭头函数是绑定不到的,因为内部没有,所以需要向上层查找


var obj = {
  name: 'xx',
  foo: () => {
    var bar = () => {
      console.log(this)
    }
    return bar
  }
}
var fn = obj.foo()
fn.apply('ccc') // window

HUMILITY
74 声望6 粉丝

DONT WASTE YOUR TIME