2016-09-07 6 views
0

В попытке правильно создавать объекты машинописи из данных, полученными через HTTP, как JSON, я изучаю возможность использования for..in петли в сочетании с .hasOwnProperty() как так:Weird .hasOwnProperty поведение

class User { 
    private name: string; 
    private age: number; 

    constructor(data: JSON) { 
     console.log('on constructor\ndata', data); 

     for (var key in data) { 
      console.log('key:', key); 
      if (User.hasOwnProperty(key)) { 
       console.log('User has key:', key); 
       this[key] = data[key]; 
      } 
     } 
    } 

    displayInfo(): string{ 
     return JSON.stringify(this); 
    } 
} 

let button = document.createElement('button'); 
button.textContent = "Test"; 
button.onclick =() => { 
    try{ 
     let json = JSON.parse('{"name": "Zorro","age": "24"}'); 
     let usr = new User(json); 
     console.log(usr.displayInfo()); 
    }catch (error){ 
     alert(error); 
    } 

} 

document.body.appendChild(button); 

Используя аналогичный код мой проект полностью не работает. Это ожидается, поскольку скомпилированный JS-код не знает о частных TS-варах, и поэтому hasOwnProperty всегда false.

Однако, я использовал Typescript Playground, и работает этот код там производит следующий вывод в консоли:

on constructor 
data Object {name: "Zorro", age: "24"} 
key: name 
User has key: name 
key: age 
{"name":"Zorro"} 

Как вы можете видеть, есть очевидно, что некоторые неожиданные вещи происходят здесь. Первый ключ распознается, и новый экземпляр пользователя инициализируется значением из JSON, но это не происходит для второго ключа.

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

+1

Вы уверены, что вы имеете в виду '' User.hasOwnProperty' не this.hasOwnProperty' или 'data.hasOwnProperty'? Обратите внимание, что 'hasOwnProperty' не является методом отражения класса, это метод объекта. – Bergi

+1

Я согласен с @Bergi - Вызов 'User' вызовет класс статически. Хотя вы можете проверить прототипированные свойства таким образом, вы не будете проверять свойства объекта, который был создан. – Jim

+0

@Bergi @Jim Я не хочу проверять свойства создаваемого объекта, который всегда возвращает false, поскольку я вызываю 'hasOwnProperty', прежде чем устанавливать значения свойств. Это будет ситуация, использующая 'this'. Что я пытался сделать, это проверить, существует ли ключ от JSON в классе, а не экземпляр, и только затем установить его значение из JSON. Это было более безопасным, поскольку, поскольку я контролирую структуру JSON, мне действительно не нужна эта проверка, но я экспериментировал и получил этот результат, который меня смутил – tiansivive

ответ

2

Как указано в комментариях, вы должны использовать this.hasOwnProperty вместо User.hasOwnProperty. И, как вы заметили, этот код все равно, потому что объявления свойств в классе фактически не создают собственные свойства объекта (их нужно будет инициализировать, чтобы это произошло).

Но почему вы получили удар по name ключам? Объект User является конструктором функция для вашего класса. Функции действительно имеют name свойство:

function fn() { } 
console.log(fn.name); // prints 'fn' 

Они не имеют age свойство, конечно.

+0

Спасибо, очень полезно – tiansivive

0

Ваш конструктор, конечно, просто посмотреть, как это, если вы хотите построить экземпляры пользователя из простых объектов JavaScript:

constructor(data: any) { 
    this.name = data.name; 
    this.age = data.age; 
}