神秘的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
相关推荐
qq_3927944815 分钟前
前端缓存策略:强缓存与协商缓存深度剖析
前端·缓存
fmdpenny38 分钟前
Vue3初学之商品的增,删,改功能
开发语言·javascript·vue.js
小美的打工日记1 小时前
ES6+新特性,var、let 和 const 的区别
前端·javascript·es6
helianying551 小时前
云原生架构下的AI智能编排:ScriptEcho赋能前端开发
前端·人工智能·云原生·架构
@PHARAOH1 小时前
HOW - 基于master的a分支和基于a的b分支合流问题
前端·git·github·分支管理
涔溪1 小时前
有哪些常见的 Vue 错误?
前端·javascript·vue.js
程序猿online1 小时前
前端jquery 实现文本框输入出现自动补全提示功能
前端·javascript·jquery
2401_897579652 小时前
ChatGPT接入苹果全家桶:开启智能新时代
前端·chatgpt
DoraBigHead2 小时前
JavaScript 执行上下文:一场代码背后的权谋与博弈
前端
Narutolxy3 小时前
从传统桌面应用到现代Web前端开发:技术对比与高效迁移指南20250122
前端