JavaScript this、闭包和箭头函数

this

this是函数内部的特殊对象之一(其他还有arguments、caller、new.target)。

this的 指向 或 值 是不确定的取决于函数的调用方式

在JavaScript中,this的指向有以下几种情况:

  • 作为对象的方法调用
  • 作为普通函数调用
  • 构造器调用
  • Function.prototype.call或Function.prototype.apply调用

此外,this在使用 闭包 和 箭头函数 时的情况我们在后面介绍两者时再谈。


1.作为对象的方法调用

当函数作为对象的方法被调用时,this指向该对象。

const obj = {
    name: 'obj',
    getName: function () {
        console.log(this.name);
    }
}
obj.getName(); //obj

2.作为普通函数调用

当函数不作为对象的属性被调用时,this指向全局对象,浏览器中是window对象。

const name = 'window'
const getName = function () {
    console.log(this.name);
}
getName(); //window

3.构造器调用

当函数被new调用时,this指向新创建的对象。

const Person = function (name) {
    this.name = name;
}
const person = new Person('person');

console.log(person.name); //person

4.Function.prototype.call或Function.prototype.apply调用

当使用call或apply调用时,this指向传入的第一个参数。

const obj = {
    name: 'obj'
}
const getName = function () {
    console.log(this.name);
}
getName.call(obj); //obj

闭包

闭包(closure)是指访问了另一个函数作用域中的变量的函数

创建闭包的最常见的方式就是在一个函数内部创建另一个函数,即嵌套函数

const a4=4;
var a5=5;
const func1 = function (a3) {
    const a2=2;
    function func2() {
        const a1=1;
        return function func3(){
            console.log(a1+a2+a3+a4+a5);
        }
    };
    return func2();
};
const result=func1(3);
result();

外部函数的活动对象位于内部函数作用域链上的第二个,该作用域链直到全局执行上下文才终止。

活动对象是包含函数的所有局部变量的对象(包括arguments对象),在函数调用时被创建,在函数执行完后被销毁,即只存在于函数执行期间。而在全局上下文中,这叫做变量对象

JavaScript this、闭包和箭头函数_第1张图片

[[Scopes]]保存了函数的作用域链。

闭包读取函数内部的变量,这使得变量始终保存在内存中,不会在函数调用后被自动清除,这会导致内存泄漏,如果闭包的作用域中有大量的变量,会占用大量的内存。

箭头函数

箭头函数是ES6新增的语法,它的this指向是固定的,指向定义时所在的对象,而不是使用时所在的对象

示例:

window.count=1;
function Counter() {
    this.count = 0;
    console.log(this);
    this.add = function () {
        this.count++;
    }
}
var counter = new Counter();
setTimeout(counter.add, 1000);
setTimeout(function () {
    console.log(counter.count);
    console.log(window.count);
}, 2000);

输出结果为

Counter {count: 0}
0
2

奇怪,为什么输出结果是0和2,而不是1和1呢?

这是因为setTimeout中的this指向了window,而不是counter,所以counter.add()中的this.count++实际上是window.count++,而不是counter.count++。

解决方法:

1.使用bind绑定this

setTimeout(counter.add.bind(counter), 1000);

2.使用_this = this保存this

function Counter() {
    var _this = this;
    this.count = 0;
    console.log(this);
    this.add = function () {
        _this.count++;
    }
}

3.使用箭头函数

function Counter() {
    this.count = 0;
    console.log(this);
    this.add = () => {
        this.count++;
    }
}

你可能感兴趣的:(JavaScript,javascript,开发语言,ecmascript)