Не
f().apply(scope);
просто
f.apply(scope);
(Нет ()
после f
.) Вы хотите использовать функцию apply
для функции f
объект, а не вызов функции f
и доступ apply
к ее возвращаемому значению.
Чтобы также передать аргументы, которые получает ваша функция в setScope
, добавьте:
f.apply(scope, arguments);
arguments
- это неявный аргумент для всех функций, который является псевдомассивом фактических аргументов, передаваемых функции во время выполнения.apply
принимает любую похожую на массив вещь в качестве второго параметра, чтобы указать аргументы, которые будут использоваться при вызове базовой функции.
Я также хотел бы, чтобы она возвращала возвращаемое значение:
return f.apply(scope, arguments);
Итак setScope
становится:
Function.prototype.setScope = function (scope) {
var f = this;
return function () {
return f.apply(scope, arguments);
}
}
Живой пример
Обратите внимание, что обычное имя для этой функции и имя, которое она имеет в новом ECMAScript5 стандарт , равен bind
(раздел 15.3.4.5; ECMAScript5 bind
также позволяет вам карри аргументы, чего не делает эта реализация).setScope
- это особенно неудачное имя, потому что оно не устанавливает scope , оно устанавливает context .
Сказав все это, вы ни за что не будетенужно setScope
в вашем Person
конструкторе.Вы можете просто сделать это:
Person = function () {
var self = this;
this.Name = "asd";
var _public = new Object();
_public.Name = function (value) {
if (value == undefined) {
return self.Name;
} else {
self.Name = value;
}
};
return _public;
};
Живой пример
Но использование bind
(он же setScope
) может быть полезным в тех местах, где вы этого не делаетенужно новое замыкание в контексте, в котором вы это делаете.
Не по теме : способ указания Person
нарушит определенные вещи, которые могут ожидать людиработать, например:
var p = new Person();
alert(p instanceof Person); // Expect "true", but in your case will be "false"
... потому что вы заменяете объект new
, созданный для вас, но возвращаете другой объект из вашего конструктора (который переопределяет значение по умолчанию).
Вместо того, чтобы создавать новый объект и возвращать его в своем конструкторе, позвольте объекту, сконструированному для вас new
, быть объектом (и, таким образом, поддерживается отношение Person
), но вы все равно можете стать действительно приватнымпеременные и методы доступа:
function Person() {
// Private variable
var name = "asd";
// Accessor function
this.Name = function(value) {
if (typeof value === "undefined") {
return name;
}
name = value;
};
}
Живой пример
Как видите, это значительно проще и сохраняет отношение instanceof
.Обратите внимание, что мы вообще не определяем наши ссылки на name
в Name
, и поэтому мы используем локальную переменную в вызове конструктора, в котором была создана наша функция Name
, которая закрывается над ней.
Я также позволил себе дать функции-конструктору имя , потому что Я не фанат анонимных функций .Мне следовало бы также дать аксессору имя:
function Person() {
// Private variable
var name = "asd";
// Accessor function
this.Name = Person_Name;
function Person_Name(value) {
if (typeof value === "undefined") {
return name;
}
name = value;
}
}
Не по теме 2 : в коде JavaScript преобладающим соглашением является использование начальных заглавных букв в именах функций только для функций конструктора (например, Person
), но не для других видов функций (например, Name
).Конечно, вы можете делать все, что захотите, но я подумал, что упомяну соглашение, поскольку другим людям будет проще читать ваш код.
Стоит отметить: Все этих методов приводят к каждому Person
объекту , имеющему собственную копию функции доступа.Если таких объектов будет много, это может быть проблемой с памятью.Если их будет всего несколько, это нормально.