函数变量添加到全局范围

时间:2014-08-11 09:05:06

标签: javascript prototype-programming

我宣布了这个功能:

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

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

makePerson()

现在,我可以在全局访问中访问firstlastfullName

有人能解释我为什么会这样。

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

1 个答案:

答案 0 :(得分:3)

这些是函数中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绑定到正在构造的对象。
  4. this可能会引起混淆,只要函数体包含this,该函数就会停止成为第一类。因此,我建议您尽量避免使用thisas does 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());