前端基础(三十二):你不知道的JavaScript - 关于this

为什么要用this

this 提供了一种隐式传递一个对象引用的方式,使得API设计的更加简洁并且易于复用。

function identify(context) {
    
    
    return context.name.toUpperCase();
}
function speak(context) {
    
    
    var greeting = "Hello, I'm " + identify(context);
    console.log(greeting);
}
var me = {
    
     name: "Kyle" };
var you = {
    
     name: "Reader" };
identify(me);   // KYLE
identify(you);  // READER
speak(me);      // Hello, I'm KYLE
speak(you);     // Hello, I'm READER
function identify() {
    
    
    return this.name.toUpperCase();
}
function speak() {
    
    
    var greeting = "Hello, I'm " + identify.call(this);
    console.log(greeting);
}
var me = {
    
     name: "Kyle" };
var you = {
    
     name: "Reader" };
identify.call(me);  // KYLE
identify.call(you); // READER
speak.call(me);     // Hello, I'm KYLE
speak.call(you);    // Hello, I'm READER

误解

this指向自身?

以下代码count1之所以打印0,是因为此函数内部的this指向的是window,并不是函数本身

function foo() {
    
    
    this.count1++;                  // this 实际上是window对象
    arguments.callee.count2++;      // 函数本身
}
// 存储循环次数
foo.count1 = 0;
foo.count2 = 0;

for (let i = 0; i < 6; i++) {
    
    
    foo();
}

// 打印循环次数
console.log(foo.count1, foo.count2); // 0 6
  • arguments.callee 已经被弃用,不建议使用,使用call来改变this指向
    // 使用call
    function foo() {
          
          
        console.log(this); // 改变了this指向之后的this指向了函数本身
        this.count++;
    }
    // 存储循环次数
    foo.count = 0;
    
    for (let i = 0; i < 6; i++) {
          
          
        foo.call(foo, null); // 改变了this指向,指向到了foo本身
    }
    
    // 打印循环次数
    console.log(foo.count); // 6
    
  • 示例:
    // n的结阶乘 n已知(请使用递归实现)
    function foo() {
          
          
        arguments.callee.res *= arguments.callee.n--;
        if (arguments.callee.n === 0 || arguments.callee.n === 1) {
          
          
            return arguments.callee.res;
        }
        return arguments.callee();
    }
    
    foo.n = 5;
    foo.res = 1; // 存储阶乘结果
    foo();
    console.log(foo.res); // 120
    
    foo.n = 10;
    foo.res = 1; // 存储阶乘结果
    foo();
    console.log(foo.res); // 3628800
    
    // n的结阶乘 n已知(请使用递归实现)
    function foo() {
          
          
        this.res *= this.n--;
        if (this.n === 0 || this.n === 1) {
          
          
            return this.res;
        }
        return this.call(foo, null);
    }
    
    foo.n = 5;
    foo.res = 1; // 存储阶乘结果
    foo.call(foo, null);
    console.log(foo.res); // 120
    
    foo.n = 10;
    foo.res = 1; // 存储阶乘结果
    foo.call(foo, null);
    console.log(foo.res); // 3628800
    

this指向函数的作用域?

this 在任何情况下都不指向函数的词法作用域。

function foo() {
    
    
    var a = 2;
    console.log(this); // {}
    this.bar(); // this.bar is not a function
}
function bar() {
    
    
    console.log(this, this.a); // 浏览器window undefined
}
foo.call({
    
    }, null);
  • 以上示例的错误:
    • 因为foo中的this指向的是{}在不同设备上this指向的环境不同),所以找不到this.bar,可修改为bar()
    • 编者试图用this联通foobar词法作用域,从而在bar中访问到a变量,但实际上this指向的还是设备环境,所以a还是找不到的。

this到底是什么

this 是在运行时进行绑定的,并不是在编写时绑定,它的上下文取决于函数调用时的各种条件。this 的绑定和函数声明的位置没有任何关系,只取决于函数的调用方式。

当一个函数被调用时,会创建一个活动记录(有时候也称为执行上下文)。这个记录会包含函数在哪里被调用(调用栈)、函数的调用方法、传入的参数等信息。this 就是记录的其中一个属性,会在函数执行的过程中用到。

猜你喜欢

转载自blog.csdn.net/weixin_43526371/article/details/125043849
今日推荐