添加到全局作用域的函数变量

Function variable added to global scope

本文关键字:函数 变量 作用域 全局 添加      更新时间:2023-09-26

我声明了这个函数:

function makePerson() {
    this.first = 'John';
    this.last = 'Oliver';
    fullName = function(){
        return this.first + this.last;
    }
}

没有实例化它,但是调用了这个函数。

makePerson()

现在我可以在全局访问中访问first, lastfullName

谁能给我解释一下为什么会这样?

注意:我没有调用它,而是实例化它并进行检查。它不是全局的,可以在函数/类/对象范围内访问。

这些是函数中this关键字的正常语义。this可能以几种方式求值,这取决于您如何调用该函数。假设我们有一个函数f,它的主体包含this关键字:

  1. f(a,b)(标准函数调用语法)中,this绑定到全局JavaScript Object,这意味着如果你在函数体中向this添加属性,你实际上是将它们添加到全局作用域。
  2. anObject.f(a,b)(方法调用语法)中,this绑定到anObject
  3. new f(a,b)(构造函数调用语法)中,this绑定到正在构造的对象。

this可能会引起混淆,一旦函数体包含this,该函数就不再是一级函数。因此,我建议您尽可能避免使用this, Douglas Crockford也是如此。

如果你想创建一个工厂函数(基于上面的原因我强烈推荐),你可以这样做:

function makePerson() {
    var person = {
        first: 'John',
        last: 'Oliver'
    };
    person.fullName = function(){
        return person.first + person.last;
    };
    return person;
}

如果你仍然想创建一个构造函数,约定要求名称大写:

function Person() {
    this.first = 'John';
    this.last = 'Oliver';
    this.fullName = function(){
        return this.first + this.last;
    };
}

最后,使用this关键字可能有很好的理由,那就是原型继承。然而,我发现构造函数语法在这方面会产生误导。幸运的是,现在我们有Object.create:

var personPrototype = {
    fullName: function () {
        return this.first + this.last;
    }
};
function makePerson(first,last) {
    var person = Object.create(personPrototype);
    person.first = first;
    person.last = last;
    return person;
}

作为最后的警告,这里有一个使用this如何导致意外约束和混乱的示例:

var cn = makePerson("Chuck","Norris");
// works fine
console.log(cn.fullName());
// does not work, fullName is not a first-class function. You cannot detach it.
var fullName = cn.fullName;
console.log(fullName());