JS中的this|青训营笔记

50 阅读3分钟

这是我参与「第五届青训营 」笔记创作活动的第5天。

本堂课重点内容

本节课介绍了JS中的this.

详细知识点介绍

在学习React的过程中,我对this的使用产生了较大的疑惑,在查阅相关资料后遂就此文。

本文代码均在浏览器环境中执行。

首先,this会在函数运行时存在于函数的上下文中,进行动态绑定。

我们可以将this的绑定规则概括为下面四种:

  1. 默认绑定
  2. 隐式绑定
  3. 显式绑定
  4. new绑定

默认绑定

看函数调用时有无主体(与函数定义时情况无关)

 // 默认绑定:独立函数调用
 function foo(){
     console.log(this)
 }
 foo() //window

这时this指向window

 var obj = {
     foo:function(){
         conosle.log(this)
     }
 }
 var test = obj.foo
 test() //window

调用时函数没有调用主体,this同样指向window

 function foo(){
     function bar(){
         console.log(this)
     }
     return bar
 }
 var fn = foo()
 fn() // window

闭包的this同样指向window

隐式绑定

.方式进行调用时,this指向.前的对象。

 let obj = {
     name:"LLLeo",
     eat: function(){
         console.log(this.name)
     },
     drink:function(){
         console.log(obj.name)
     }
 }
 obj.eat() // LLLeo
 obj.drink() // LLLeo

object对象会被js引擎绑定到函数中的this里。

对于隐式绑定来说,必须在调用的对象内部存在一个对函数的引用。如果没有这样的引用,在调用时会报找不到该函数的错误。js引擎也正是通过这个引用实现了对this的绑定。

显式绑定

如果我们不希望在对象内部包含这个函数的引用,同时又希望在这个对象上进行强制调用,我们可以使用callapply方法:

  • 二者第一个参数都是为this准备的对象
  • apply后面的参数为原函数的参数数组
  • call后面的参数为原函数的参数列表
  • V8引擎对apply进行了性能优化,更推荐使用
 function foo(item1,item2){
     console.log(this,item1,item2)
 }
 var obj = {
     name:"obj"
 }
 foo.call(obj,[1,2]) // window 1 2
 foo.apply(obj,1,2) // window 1 2

我们可以使用bind对函数进行强制绑定,减少不断.apply的重复。

 function foo(item1,item2){
     console.log(this,item1,item2)
 }
 var obj = {
     name:"obj"
 }
 // 默认绑定于显式绑定冲突,显式绑定优先级更高
 let newFoo = foo.bind(obj)
 newFoo(1,2)

new绑定

我们可以使用new关键字将js中的函数当做一个类的构造函数来使用。

当使用new关键字来调用函数时:

  1. 创建一个全新的对象
  2. 这个新对象会执行prototype连接
  3. 这个新对象会绑定到函数调用的this上
  4. 如果函数没有返回其他对象,表达式会返回这个对象
 function Person(name,age){
     this.name = name;
     this.age = age;
 }
 let person = new Person("LLLeo",21)

优先级规则

  1. 默认绑定的优先级最低

  2. 显式绑定优先级高于隐式绑定

     function foo(){
         console.log(this)
     }
     let obj = {
         foo: foo.bind("LLLeo");
     }
     obj.foo() // LLLeo
    
  1. new绑定优先级高于隐式绑定
  1. new绑定高于显式绑定

     // new不能和apply/call一起使用
     fuction foo(){
         console.log(this)
     }
     let var = foo.bind("LLLeo")
     let obj = new var() // foo {}