this

2019-03-20  本文已影响0人  _theFeng
let me = {
  name: 'seymoe'
}
function toUpperCase() {
  return this.name.toUpperCase()
}

toUpperCase.call(me)  // 'SEYMOE'

可以不使用this

// 通过传参的形式
let me = {
  name: 'seymoe'
}
function toUpperCase(person) {
  return person.name.toUpperCase()
}

toUpperCase(me)  // 'SEYMOE'

this的调用栈和调用点

function baz() {
  // 调用栈是‘baz’,调用点是全局作用域
  console.log('baz')
  bar()   2. // bar的调用点
}
function bar() {
  // 调用栈是‘baz - bar’,调用点位于baz的函数作用域内
  console.log('bar')
}

baz()  // 1. baz的调用点

this的指向问题

var a = 2
function foo() {
  console.log(this.a)
}
function bar() {
  foo()
}
foo()  // 2
bar()  // 2
// foo 是一个直白的毫无修饰的函数引用调用,
// 所以默认绑定了全局对象,
// 当然如果是严格模式 "use strict" this 将会是 undefined。
var a = 2
function foo() {
  console.log(this.a)
}
(function (){
  "use strict";
  foo()  // 2
})()
// 注意: 虽然是基于调用点,
但只要foo的内容没在严格模式下,那就默认绑定全局对象。
function foo() {
  console.log(this.a)
}

let obj = {
  a: 2,
  foo: foo
}
obj.foo()  // 2
var a = 3
function foo() {
  console.log(this.a)
}

let obj = {
  a: 2,
  foo: foo
}

let bar = obj.foo
bar()  // 3

// 另一种微妙的情况
function doFoo(fn) {
    fn && fn()
}

doFoo(obj.foo)  // 3
function foo() {
    console.log(this.a)
}
let obj = {
    a: 2
}
foo.call(obj)   // 2
var obj = {
  a: 2
}
function foo(something) {
    console.log(this.a, something)
    return this.a + something
}
var bar = foo.bind(obj)
bar(' is a number.')  // 2 ,'is a number.'

new 操作符调用时会创建一个全新对象,连接原型链,并将这个新创建的对象设置为函数调用的 this 绑定,(默认情况)自动返回这个全新对象。

function Foo(a) {
  this.a = a
}
let bar = new Foo(2)
console.log(bar.a)  // 2

如果是 new 调用,this 是新构建的对象;
call、apply 或bind ,this 是明确指定的对象;
是用环境对象(或容器)调用的,this 是这个容器;
默认绑定,严格模式为 undefined,否则是global(全局)对象。

因为箭头函数不会像普通函数去使用 this, 箭头函数的 this 和外层的 this 保持一致。这种保持一致是强力的,无法通过 call、apply 或 bind来改变指向。

const obj = {
  a: () => {
    console.log(this)
  }
}
obj.a() // window
obj.a.bind({})()  // window
上一篇 下一篇

猜你喜欢

热点阅读