Функциональная переменная, добавленная в глобальную область видимости
Я объявил функцию:
function makePerson() {
this.first = 'John';
this.last = 'Oliver';
fullName = function(){
return this.first + this.last;
}
}
Не создавал его экземпляр, а вызвал эту функцию.
makePerson()
Теперь я могу получить доступ first, last и fullName в глобальном доступе.
Может ли кто-нибудь объяснить мне, почему это происходит?
Примечание: вместо того, чтобы позвонить, я создал экземпляр и проверил. Он не является глобальным и доступен в области функций/классов/объектов.
1 ответ:
Это нормальная семантика ключевого слова
thisв функции.thisможет быть вычислено несколькими способами, в зависимости от того, как вы вызываете функцию. Допустим, у нас есть функцияf, тело которой содержит ключевое словоthis:
- В
f(a,b)(стандартный синтаксис вызова функции)thisпривязан к глобальному JavaScriptObject, что означает, что если вы добавляете свойства кthisв теле функции, вы фактически добавляете их в глобальную область видимости.- В
anObject.f(a,b)(синтаксис вызова метода),thisсвязан сanObject.- В
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