This和箭头函数的使用 (均是在非严格模式下)

50 阅读4分钟

This和箭头函数的使用 (均是在非严格模式下)

this的绑定规则

this到底指向什么呢?

QQ截图20240616202037.png

  • this的绑定规则:
    • 默认绑定
    • 隐式绑定
    • 显式绑定
    • new绑定
    QQ截图20240616204739.png

apply/call/bind

apply和call的区别

QQ截图20240616210240.png

bind的规则

  • bind函数会返回一个this总是绑定所绑定的函数
function foo() {
  console.log("foo", this)
}

var obj = {
  name: "zsy",
  age: 18
}

foo() // this -> window

// 需求:调用foo时,总是绑定到obj对象身上(不希望obj对象身上有函数)
var bar = foo.bind(obj)

bar() // this -> obj

运行结果:

QQ截图20240616211615.png

this的绑定优先级

  • 默认绑定的优先级最低(隐式绑定优先级高于默认绑定)

    function foo() {
      console.log("foo", this) // this -> obj
    }
    
    var obj = {
      foo: foo
    }
    
    obj.foo()
    

    运行结果:

    QQ截图20240616215410.png

  • 显示绑定优先级高于隐式绑定(call、apply和bind)

    function foo() {
      console.log("foo", this) // this -> String {"abc"}
    }
    
    var obj = {
      foo: foo
    }
    
    obj.foo.call("abc") // call和apply都可以
    

    运行结果:

    QQ截图20240616215455.png

  • new绑定优先级高于隐式绑定

    function foo() {
      console.log("foo", this) // this -> {}(new关键字创建的对象)
      console.log(this === obj) // false
    }
    
    var obj = {
      foo: foo
    }
    
    new obj.foo()
    

    运行结果:

    QQ截图20240616215945.png

  • new绑定的优先级高于bind

    function foo() {
      console.log("foo", this) // this -> {}(new关键字创建的对象)
    }
    
    var obj = {
      foo: foo
    }
    
    var bar = foo.bind("aaa") // 通过bind函数显示绑定string aaa
    new bar()
    

    运行结果:

    QQ截图20240621201544.png

    • new绑定和call、apply是不允许同时使用的
    • new绑定可以和bind一起使用,new绑定优先级更高
  • bind绑定的优先级高于call和apply

    function foo() {
      console.log("foo", this) // this - > string {'aaa'}
    }
    
    var obj = {
      foo: foo
    }
    
    var bar = foo.bind("aaa") // 通过bind函数显示绑定string aaa
    bar.call("bbb") // 通过call函数显示绑定string bbb (call和apply函数用法可以说是一样的)
    

    运行结果:

QQ截图20240621202152.png

绑定之外的情况

忽略显示绑定

function foo() {
  console.log("foo", this) // this - > window对象
}

var obj = {
  foo: foo
}

foo.call(null) // 显示绑定null和undefined作用是一样的

运行结果:

QQ截图20240621202938.png

间接函数引用

var obj1 = {
  name: "obj1",
  foo: function() {
    console.log("foo", this) // this -> window对象
  }
}

var obj2 = {
  name: "obj2"
}; // 这里一定要加分号(;)

(obj2.foo = obj1.foo)() // 相当于独立调用函数

运行结果:

QQ截图20240621210424.png

箭头函数的使用(ES6)

  • 箭头函数不会绑定this、arguments属性

  • 箭头函数不能作为构造函数来使用(不能和new一起来使用,会抛出错误)

  • 箭头函数的简写

    var arrs = [1, 2, 3, 4, 5, 6, 7, 8, 9]
    
    var num = arrs.filter(element => element % 2 === 0)
    console.log(num)
    

    运行结果:

    QQ截图20240621212618.png

    var obj = {
      name: "obj"
    }
    
    var resultFn = () => ({obj}) // 如果箭头函数简写,要返回对象时必须用()包起来。否则{}包起来的是执行体
    console.log(resultFn())
    

    运行结果:

    QQ截图20240621213310.png

  • 箭头函数实现nums的所有偶数平方之和 (练习箭头函数的简写以及高阶函数的使用)

    var nums = [20, 30, 11, 15, 111]
    
    var result = nums.filter(item => item % 2 === 0)
                      .map(item => item * item)
                      .reduce((preItem, item) => preItem + item)
    console.log(result) // 1300
    
  • 箭头函数中,压根没有this。即箭头函数不绑定this(this是从上层作用域中查询的)

    var obj = {
      name: "obj",
      foo: function() {
        var bar = () => {
          console.log("bar", this) // this -> obj对象(此处的this是上层作用域foo函数的this)
        }
    
        return bar
      }
    }
    
    var fn = obj.foo() // foo函数是被obj对象,隐式调用的
    fn.call("aaa")
    

    运行结果:

    QQ截图20240621215603.png

this面试题分析

面试题一

var name = "window"

var person = {
  name: "person",
  sayName: function () {
    console.log(this.name)
  }
}

function sayName() {
  var sss = person.sayName;
  sss(); // 默认绑定, this -> window
  person.sayName(); // 隐式绑定, this -> person
  (person.sayName)(); // 隐式绑定, this -> person
  (b = person.sayName)(); // 默认绑定, this -> window (间接函数引用)
}

sayName()

面试题二

var name = "window"

var person1 = {
  name: "person1",
  foo1: function () {
    console.log(this.name)
  },
  foo2: () => console.log(this.name),
  foo3: function () {
    return function () {
      console.log(this.name)
    }
  },
  foo4: function () {
    return () => {
      console.log(this.name)
    }
  }
}

var person2 = {
  name: "person2"
}

person1.foo1() // 隐式绑定, person1
person1.foo1.call(person2) // 显式绑定优先级高于隐式绑定, person2

person1.foo2() // 箭头函数无this, this是从上层作用域查询到的(this -> window), window

// 不管隐式绑定还是显式绑定都是对foo2函数的, 但foo2函数是箭头函数, this是从上层作用域查询到的(this -> window)
person1.foo2.call(person2) // window

person1.foo3()() // 默认绑定, window

// 显式绑定优先级高于隐式绑定, foo3函数的this -> person2, 但foo3函数执行完返回一个新函数属于是独立调用函数this -> window
person1.foo3.call(person2)() // window
person1.foo3().call(person2) // 显示绑定, person2

// foo4函数被执行时,this -> person1, 返回箭头函数,而箭头函数的this是从上层作用域查询到的(this -> person1)
person1.foo4()() // person1
person1.foo4.call(person2)() // person2
person1.foo4().call(person2) // person1

运行结果:

QQ截图20240624193444.png

面试题三

var name = "window"

function Person(name) {
  this.name = name
  this.foo1 = function () {
    console.log(this.name)
  },
  this.foo2 = () => console.log(this.name),
  this.foo3 = function () {
    return function () {
      console.log(this.name)
    }
  },
  this.foo4 = function () {
    return () => {
      console.log(this.name)
    }
  }
}

var person1 = new Person("person1")
var person2 = new Person("person2")

person1.foo1() // person1
person1.foo1.call(person2) // person2

person1.foo2() // person1
person1.foo2.call(person2) // person1

person1.foo3()() // window
person1.foo3.call(person2)() // window
person1.foo3().call(person2) // person2

person1.foo4()() // person1
person1.foo4.call(person2)() // person2
person1.foo4().call(person2) // person1

运行结果:

QQ截图20240624200631.png

面试题四

var name = "window"

function Person(name) {
  this.name = name
  this.obj = {
    name: "obj",
    foo1: function() {
      return function() {
        console.log(this.name)
      }
     },
     foo2: function() {
      return () => {
        console.log(this.name)
      }
     }
  }
}

var person1 = new Person("person1")
var person2 = new Person("person2")

person1.obj.foo1()() // window
person1.obj.foo1.call(person2)() // window
person1.obj.foo1().call(person2) // person2

person1.obj.foo2()() // obj
person1.obj.foo2.call(person2)() // person2
person1.obj.foo2().call(person2) // obj

运行结果:

QQ截图20240624201810.png