likes
comments
collection
share

通过简单的几个代码来带大家掌握this的绑定,翻越JavaScript中的大山!

作者站长头像
站长
· 阅读数 28

this

JavaScript 中的 this 是一个特殊的关键字,它在函数内部指向函数当前所属的对象。this 的值在函数被调用时确定,而不是在函数被定义时确定。

this的绑定

默认绑定规则

1.默认绑定规则:当函数作为普通函数调用时,this 指向全局对象(在浏览器环境中通常是 window 对象)看如下代码:

function foo(){     //默认绑定规则

    function bar(){
        console.log(this)   //此时this指向全局window
    }
    bar()
}
foo()

this是bar()函数中的,bar()的外层作用域是foo()函数体,我们说函数在哪个词法作用域中生效,this就指向哪里,要使bar()函数生效,所以得foo()函数生效,此时foo()函数的词法作用域为全局,所以this指向全局。

当内层有多个函数体包裹时,且为独立函数调用时this都指向window,因为this的查找就好似于原型链,不断的查找,直至this查到的对象为window。

通过简单的几个代码来带大家掌握this的绑定,翻越JavaScript中的大山!

隐式绑定规则

隐式绑定规则:当一个函数被对象所拥有且调用时,函数的this指向该对象。

function foo(){
    console.log(this.a)
}

var obj = {
    a:1,
    foo:foo     
}

obj.foo()   

foo未带()表示引用,带了()表示调用,引用则表示foo()被obj所拥有,相当于foo:function foo(){ console.log(this.a)} 。

this在foo()函数中,但此时foo()被obj所拥有且被调用,所以此时this指向obj,输出的this.a=obj.a,a=1;

隐式丢失

隐式丢失:当函数被多个对象链式调用时,this指向引用函数的那个对象(就近原则)。

我们来看如下代码:此时this.a指向谁呢,输出的值又为多少呢?

//隐式丢失:当函数被多个对象链式调用时,this指向引用函数的那个对象
function foo(){
    console.log(this.a)
}
var obj = {
    a:1,
    foo:foo     
}
var obj2 = {
    a:2,
    obj:obj
}
obj2.obj.foo() 

在obj中,foo引用了foo()函数,所以此时foo()为obj所拥有,又因为obj2中引用了obj变量,所以obj为obj2所拥有,于是当我们全局调用时 obj2.obj.foo(),结果this是指向obj呢还是obj2呢?

通过简单的几个代码来带大家掌握this的绑定,翻越JavaScript中的大山!

通过结果可以看出,输出的是obj中的a值,所以说this还是指向了obj而不是obj2,所以我们就称这种绑定为隐式丢失(指向就近的那个)。

显式绑定

在 JavaScript 中,你可以使用 callapplybind 方法来显式地绑定函数内部的 this 值。这些方法允许你在调用函数时手动指定 this 的值,而不是依赖于函数的调用方式。

1.使用call方法

查看一段代码:

function foo(){
 console.log(this.a);
}
var obj = {
  a:1
}
foo.call(obj)

原本的this指向的是window(foo()独立调用时),此时使用call方法,使得this的绑定改绑到括号里面的obj当中,此时的输出为1。

通过简单的几个代码来带大家掌握this的绑定,翻越JavaScript中的大山! 此外call还可以接收参数,看如下代码:
function foo(x,y){
 console.log(this.a,x+y);
}
var obj = {
  a:1
}
foo.call(obj,4,5)
通过简单的几个代码来带大家掌握this的绑定,翻越JavaScript中的大山!

2.使用apply方法

apply的用法与call相似,但是apply接收参数的方法是数组的形式。

function foo(x,y){
 console.log(this.a,x+y);
}
var obj = {
  a:1
}
foo.apply(obj,[4,5])   //数组的形式[4,5]
通过简单的几个代码来带大家掌握this的绑定,翻越JavaScript中的大山!

3.使用bind方法

bind 方法创建一个新的函数,并将指定的 this 值绑定到新函数。不过,bind 方法不会立即调用原函数,而是返回一个新函数。该新函数的 this 值已经被绑定,但你可以稍后再调用它。

function greet() {
  console.log("你好,我是" + this.name);
}

var obj = { name: "对象" };
var boundGreet = greet.bind(obj);
boundGreet(); // 输出:你好,我是对象

通过简单的几个代码来带大家掌握this的绑定,翻越JavaScript中的大山!

call、apply及bind三者的比较(显式绑定)

  • call 和 apply 是直接调用函数并指定 this 的值,而 bind 是创建一个新函数。
  • call 和 apply 需要立即调用原函数,而 bind 则可以延迟调用。
  • call 和 apply 的区别在于参数的传递方式,call 是参数列表,apply 是参数数组。

显式绑定 this 可以确保函数在任何上下文中都能得到正确的 this 值,从而提高代码的可靠性和可重用性。

new绑定

this指向实例对象(之前的文章中有细讲new)

箭头函数

var foo =()=>{
    console.log(123);
}
foo()                //与var foo =function(){} 相等
通过简单的几个代码来带大家掌握this的绑定,翻越JavaScript中的大山!

那么箭头函数和普通的函数有什么区别呢?我们通过代码来表示:

var obj ={
  a:1
}
var foo =()=>{
  console.log(this.a);
}
foo.call(obj) 


var foo =function (){
  console.log(this.a);
}
foo.call(obj) 
通过简单的几个代码来带大家掌握this的绑定,翻越JavaScript中的大山!

此时的前者的运行结果为undefined,后者的运行结果为1,为什么呢?

是因为箭头函数中并没有this这一说,所以拿不到obj中的值,那么箭头函数中的this指向的是foo()函数外的window

例如:

var obj = {
  a:1
}
function foo(){
  var bar= ()=>{
    console.log(this);
  }
  bar()
}
foo.call(obj)

箭头函数中没有this,所以this指向的是foo(),而foo.call(obj)使得this指向obj,所以可以输出a:1

通过简单的几个代码来带大家掌握this的绑定,翻越JavaScript中的大山! 因为箭头函数中没有this,所以箭头函数也不能通过new创建实例对象!
转载自:https://juejin.cn/post/7366836510690197539
评论
请登录