神秘的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
相关推荐
崔庆才丨静觅6 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby60617 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了7 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅7 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅8 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅8 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment8 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅8 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊8 小时前
jwt介绍
前端
爱敲代码的小鱼8 小时前
AJAX(异步交互的技术来实现从服务端中获取数据):
前端·javascript·ajax