神秘的this

神秘的this

this在 JavaScript 中是一个非常重要的关键字,它的指向在不同的情况下会有所不同。可以把this想象成一个"指针",它总是指向当前正在执行的代码所在的对象。

足够先进的技术都和魔法无异 --- Arthur C.Clarke

this又存在于哪里?

1.全局
2.函数体内

this的绑定规则

kotlin 复制代码
1.默认绑定:当一个函数默认调用时,不带任何修饰符的调用,该函数的this指向window
2.隐式绑定:当一个函数被某个对象所拥有,或者函数被某个上下文对象调用时,该函数中的this指向该上下文对象
3.隐式丢失:当一个函数被多个对象链式调用时,this指向最近的那个对象
4.显式绑定:通过call,apply,bind,将函数的this掰弯一个对象中
5.new绑定:this指向实例对象

没看懂对不对?单看文字没有例子,看不太懂

1.默认绑定:

javascript 复制代码
当一个函数默认调用时,不带任何修饰符的调用,该函数的this指向window,即指向全局对象

案例一

ini 复制代码
var a =1 
console.log(a);

function foo(){
    var b = 1;
    console.log(b);
}
foo();//这就是不带任何修饰符的调用

深度解析

scss 复制代码
//this指代,函数生效的词法作用对象
function foo(){
    var a = 1 
    function bar(){
        console.log(this.a); //
    }
    bar(); 
    //bar在foo的作用域里面生效
    //foo的词法作用域是全局
    //this指代全局对象即window
}
foo();

升级一下

scss 复制代码
var a = 1
function foo(){
    var a = 2
    function bar(){
        var a = 3
        function baz(){ 
            console.log(this.a);// 打印undefined
        }
        baz();
        //baz在bar的作用域里面生效
        //bar的词法作用域是foo
        //foo的词法作用域又是全局,所以this指向去全局对象
    }
   bar();
}
foo();

再升级一下

javascript 复制代码
var a = 1
function foo(){
    var a = 2
    function bar(){
        var a = 3
        function baz(){ 
            console.log(this.a);// 打印undefined
        }
        return baz;
    }
    var d = bar();
    d() //d即baz在foo中生效,foo的词法作用域是全局。this指代全局对象

}
foo();

奇怪为什么打印的还是undefined吗?this指向的是全局对象。this.a表示对象的属性,而全局这个对象中并没有a这个属性。var a = 1;a只是一个变量。

小结:默认绑定的就是全局对象

2.隐式绑定:

当一个函数被某个对象所拥有,或者函数被某个上下文对象调用时,该函数中的this指向该上下文对象

javascript 复制代码
var obj = {
    a :1,
    foo: foo
}

function foo(){
    console.log(this.a);
}
obj.foo()//当一个函数被某个对象所拥有

温馨提示:obj.foo和obj.foo()的区别

obj.foo 得到的是函数 foo 本身,即得到返回值

obj.foo() 则是对这个函数进行调用执行,会执行函数内部的代码,在这个例子中就是输出 this.a 的值。

升级一下

yaml 复制代码
var obj1 = {
    name: 'obj1',
    method1: function() {
      console.log('obj1 method1 this:', this);
    }
  };

  var obj2 = {
    name: 'obj2',
    method2: obj1.method1
  };

  obj1.method1();
  // obj1 method1 this: { name: 'obj1', method1: [Function: method1]}

  obj2.method2();
  //obj1 method1 this: { name: 'obj2', method2: [Function: method1]}
  
  
 

当执行 obj1.method1() 时,此时 this 指向 obj1 对象,所以会打印出 obj1 对象本身。

当执行 obj2.method2() 时,这是因为 obj2.method2 是对 obj1.method1 函数的引用,当调用 obj2.method2() 时,实际上是在调用 obj1.method1 函数,并且 this 的值被绑定到了 obj2 对象上。

3.隐式丢失:

当一个函数被多个对象链式调用时,this指向最近的那个对象

javascript 复制代码
var obj1 = {
    name: 'obj1',
    method1: function() {
      console.log('obj1 method1 this:', this);
    }
  };

  var obj2 = {
    name: 'obj2',
    method2: obj1
  };

  obj2.method2.method1()//相当于obj2.obj1.method();被对象链式调用选最近的
  //打印obj1 method1 this: { name: 'obj1', method1: [Function: method1] }
  
  

对比

javascript 复制代码
var obj1 = {
name: 'obj1',
method1: function() {
  console.log('obj1 method1 this:', this);
}
  };

  var obj2 = {
    name: 'obj2',
    method2: obj1
  };

  obj2.method2.method1()
  //obj1 method1 this: { name: 'obj1', method1: [Function: method1] }

javascript 复制代码
  var obj1 = {
    name: 'obj1',
    method1: function() {
      console.log('obj1 method1 this:', this);
    }
  };

  var obj2 = {
    name: 'obj2',
    method2: obj1.method1
  };

  obj2.method2()
//obj1 method1 this: { name: 'obj2', method2: [Function: method1]}

第一个就是明显的隐式绑定,对象链式绑定,可以拆分成(obj2.obj1).method()

第二个可以这样拆分,obj2.(obj1.method()),obj2引用了method方法

4.显式绑定:

通过call,apply,bind,将函数的this掰弯一个对象中

javascript 复制代码
function myFunction(a, b) {
  console.log('this.name:', this.name, ', a:', a, ', b:', b);
}

// 使用 call
const obj1 = { name: 'obj1' };
myFunction.call(obj1, 1, 2);//this.name: obj1 , a: 1 , b: 2

这里使用 call 方法来调用 myFunction 函数。call 方法的第一个参数 obj1 就是明确指定的 this 的值,即让 myFunction 函数内部的 this 指向 obj1 对象。后面的 12 则是传递给函数的参数。所以在函数内部,this.name 会是 obj1name'obj1'a1b2

ini 复制代码
// 使用 apply
const obj2 = { name: 'obj2' };
myFunction.apply(obj2, [3, 4]);//this.name: obj2 , a: 3 , b: 4

apply 方法与 call 类似,也是用于指定 this 的指向。不同的是,它的第二个参数是一个数组,数组中的元素就是要传递给函数的参数。所以这里函数内部 this.nameobj2name 'obj2'a3b4

ini 复制代码
// 使用 bind
const obj3 = { name: 'obj3' };
const boundFunction = myFunction.bind(obj3);
boundFunction(5, 6);//this.name: obj3 , a: 5 , b: 6

bind 方法会创建一个新的函数,这个新函数的 this 被永久地绑定为指定的对象(这里是 obj3)。然后调用这个新函数 boundFunction 时,它内部的 this 就会是 obj3,参数为 56。同样地,this.nameobj3name 'obj3'

5.new绑定:

this指向实例对象

javascript 复制代码
function foo(a){
  this.a;
}

var bar  = new foo(2)
//this指向实例对象
console.log(bar.a);//2
相关推荐
阿伟来咯~15 分钟前
记录学习react的一些内容
javascript·学习·react.js
吕彬-前端20 分钟前
使用vite+react+ts+Ant Design开发后台管理项目(五)
前端·javascript·react.js
学前端的小朱23 分钟前
Redux的简介及其在React中的应用
前端·javascript·react.js·redux·store
guai_guai_guai32 分钟前
uniapp
前端·javascript·vue.js·uni-app
也无晴也无风雨33 分钟前
在JS中, 0 == [0] 吗
开发语言·javascript
bysking1 小时前
【前端-组件】定义行分组的表格表单实现-bysking
前端·react.js
王哲晓2 小时前
第三十章 章节练习商品列表组件封装
前端·javascript·vue.js
fg_4112 小时前
无网络安装ionic和运行
前端·npm
理想不理想v2 小时前
‌Vue 3相比Vue 2的主要改进‌?
前端·javascript·vue.js·面试
酷酷的阿云2 小时前
不用ECharts!从0到1徒手撸一个Vue3柱状图
前端·javascript·vue.js