Привилегированные методы - как получить значения свойств, которые передаются в функцию?

(пример из книги, но я, кажется, не понимаю)

    function User (properties){
       for( var i in properties){
           (function(){
               this["get"+i] = function () { return properties[i];};
               this["set"+i] = function (valueOne) { properties[i] = valueOne; }; 
           }) ();
        }// END for
    }// END User

var userOne = new User ({ name: "Billy", age: 35 });
userOne.getname(); 

Когда я запускаю это, пользователь не имеет getname метод. Как сделать так, чтобы привилегированный метод работал?

4 ответа

Решение

Это потому, что вы использовали немедленно вызванную функцию

    for( var i in properties){
       (function(){  //<--- This
           this["get"+i] = function () { return properties[i];};
           this["set"+i] = function (valueOne) { properties[i] = valueOne; }; 
       }) ();
    }

Удалите его, и он все равно не будет работать, но ваши методы будут там. Чтобы он работал полностью, вы должны сохранить i

    for( var i in properties){
       (function(i){  //<--- This
           this["get"+i] = function () { return properties[i];};
           this["set"+i] = function (valueOne) { properties[i] = valueOne; }; 
       }) (i); //<--- and this
    }

Последний вопрос не так интересен (хотя и связан с) первым.

Javascript имеет только то, что известно как "область действия функции", что означает, что единственное, что ограничивает область действия функции - это... ну... функция. Таким образом, обычным делом является использование IIFE, подобных этому, внутри циклов for или во многих местах, где вы не хотите, чтобы переменные вытекли.

Тем не менее this Параметр в JavaScript странный. Поймите следующее, и это сэкономит вам массу хлопот: thisв javascript ничем не отличается от любого другого параметра.

Позволь мне объяснить.

Есть четыре способа вызвать функцию в JavaScript.

myFn.call("this param", "param 1", "param 2"); //this is "this param"
myFn.apply("this param", ["param 1", "param 2"]); //this is "this param"
myFn("param 1", "param 2"); 
//javascript takes a guess at what `this` should be - 
//usually it is set to the global `window`.
new myFn("param 1", "param 2"); 
//`this` is a new function with its' prototype set to myFn.prototype

Если бы вы всегда использовали .call форма двусмысленности исчезнет, ​​и вы можете видеть, что this точно так же, как любой другой параметр. Однако это дополнительный синтаксис, и люди предпочитают использовать более простую форму, что означает, что вы должны учитывать правила для того, что является "этим".

Поэтому то, что вы делаете в своем примере, это размещение геттеров и сеттеров на глобальном уровне. window объект.

Здесь я сделаю заявление, что ваша книга, вероятно, не согласна с этим, но я извлек его из многолетнего обучения, работы и преподавания javascript:

Не используйте new а также this ключевые слова.

Эти два ключевых слова вводят в JS массу концепций, которые сбивают с толку и действительно - если вы не делаете что-то очень чувствительное к производительности (вы не знаете, я так думаю, но это не так) - не обязательно. Вместо этого создайте новые объекты просто так:

var user = { name: "Billy", age: 35 };

если вам абсолютно необходимы геттеры и сеттеры, это сделает это:

function createObjectWithProps (properties){
   var obj = {};
   var state = {}[
   for( var k in properties){
       (function(key) {
           obj["get"+key] = function () { return state[key];};
           obj["set"+key] = function (valueOne) { state[key] = valueOne; }; 
        })(k)
    }
    return obj;
}

var userOne = createObjectWithProps ({ name: "Billy", age: 35 });
userOne.getname(); 

Хотя я пойду еще дальше, чтобы заявить, что геттеры и сеттеры не очень полезны в js, и когда вы их используете, стандартно следовать шаблону, подобному тому, что делает нокаут.

Вам нужны оба this а также i захвачено в закрытии:

function User (properties){
   for( var i in properties){
       (function(t, i){
           t["get"+i] = function () { return properties[i];};
           t["set"+i] = function (valueOne) { properties[i] = valueOne; }; 
       }) (this, i);
    }// END for
}// END User

this это не то, что вы думаете, это. Так как вы вызвали IIFE ни на что, this будет глобальной областью действия, поэтому окно получит методы getnameи т. д., что не то, что вы ожидали.

Чтобы исправить это, если вы хотите сохранить IIFE, вам нужно вызвать его в правильном контексте:

function User (properties){
       for( var i in properties){
           (function(key){
               this["get"+key] = function () { return properties[key];};
               this["set"+key] = function (valueOne) { properties[key] = valueOne; }; 
           }).call(this, i);
        }// END for
    }// END User

var userOne = new User ({ name: "Billy", age: 35 });
userOne.getname(); 

Обратите внимание, что вы также забыли передать i аргумент функции и интерпретировать его как параметр. В противном случае все функции будут привязаны к одному и тому же ключу, таким образом, userOne.getname вернется 35.

Проблема заключается в ключевом слове "это".

Поскольку вы используете его внутри немедленно вызванной функции, он указывает на глобальную область.

попробуй это:

function User (properties){

   for( var i in properties){
       (function(self,i){
           self["get"+i] = function () { return properties[i];};
           self["set"+i] = function (valueOne) { properties[i] = valueOne; }; 
       }) (this,i);
    }// END for
}// END User
Другие вопросы по тегам