Функциональная переменная, добавленная в глобальную область видимости



Я объявил функцию:



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


Не создавал его экземпляр, а вызвал эту функцию.



makePerson()


Теперь я могу получить доступ first, last и fullName в глобальном доступе.



Может ли кто-нибудь объяснить мне, почему это происходит?

Примечание: вместо того, чтобы позвонить, я создал экземпляр и проверил. Он не является глобальным и доступен в области функций/классов/объектов.
373   1  

1 ответ:

Это нормальная семантика ключевого слова 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 как можно больше, , как это делает Дуглас Крокфорд.

Если вы хотите сделать заводскую функцию (что я настоятельно рекомендую по вышеуказанной причине), вы можете сделать это так способ :

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());

Comments

    Ничего не найдено.