2017-01-12 2 views
3

при условии, что объект может содержать собственное свойство, называемое «hasOwnProperty»:Каков подходящий/рекомендуемый способ использования hasOwnProperty?

> a={abc: 123}; 
{ abc: 123 } 
> a.hasOwnProperty("abc"); 
true 
> a['hasOwnProperty'] = 1; 
1 
> a.hasOwnProperty("abc"); 
TypeError: a.hasOwnProperty is not a function 
... 

Это работает, своего рода уродливый интерфейс, если вы думаете о Object.keys(), Object.assign() и т.д .. Итак, там лучший способ?

> Object.hasOwnProperty.call(a, "abc"); 
true 
> Object.hasOwnProperty.call(a, "hasOwnProperty"); 
true 

И почему это решение не должно быть единственным рекомендуемым способом? Использование методов непосредственно из объекта представляется как рецепт сбоя, особенно если он содержит внешние данные (не находится под контролем)

+0

Может быть полезно: http://stackoverflow.com/questions/12017693/why-use-object-prototype-hasownproperty -callmyobj-prop-вместо-myobj-hasow – tymeJV

ответ

0

Соответствующий/рекомендуемый способ использования hasOwnProperty является фильтром или средством для определения того, является ли объект ... ну, имеет это свойство. Просто так, как вы его используете во второй команде a.hasOwnProperty('abc').

Переписывая объект hasOwnProperty с a['hasOwnProperty'] = 1, хотя он безопасен и действителен, просто удаляет возможность использовать функцию hasOwnProperty для этого объекта.

Я пропустил ваш истинный вопрос здесь? Похоже, вы уже это знали из своего примера.

По

«с использованием методов непосредственно от объекта, кажется, как рецепт для отказа

вы имеете в виду что-то вроде этого:

> dog = {speak: function() {console.log('ruff! ruff!')}}; 
> dog.speak(); // ruff! ruff! 

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

+0

Я имею в виду загрузку данных (таких как токенизация документа) в объект. Документ может быть о javascript и может содержать токен 'hasOwnProperty'. Конечно, использование объектов с помощью методов является мощным, но это не мой вопрос. – niry

0

Если вы можете использовать ECMAScript 2015, вы можете попробовать Reflect.getOwnPropertyDescriptor. Он возвращает дескриптор свойства данного свойства, если он существует на объекте, в противном случае он не определен.

Для упрощения вы можете создать эту функцию:

var hasOwnProp = (obj, prop) => Reflect.getOwnPropertyDescriptor(obj, prop) !== undefined; 

var obj = new Object(); 
 
obj.prop = 'exists'; 
 

 
console.log('Using hasOwnProperty') 
 
console.log('prop: ' + obj.hasOwnProperty('prop'));    
 
console.log('toString: ' + obj.hasOwnProperty('toString'));   
 
console.log('hasOwnProperty: ' + obj.hasOwnProperty('hasOwnProperty')); 
 

 
var hasOwnProp = (obj, prop) => Reflect.getOwnPropertyDescriptor(obj, prop) !== undefined; 
 

 
console.log('Using getOwnPropertyDescriptor') 
 
console.log('prop: ' + hasOwnProp(obj, 'prop')); 
 
console.log('toString: ' + hasOwnProp(obj, 'toString')); 
 
console.log('hasOwnProperty: ' + hasOwnProp(obj, 'hasOwnProperty')); 
 

 
obj['hasOwnProperty'] = 1; 
 

 
console.log('hasOwnProperty: ' + hasOwnProp(obj, 'hasOwnProperty'));

+0

Спасибо за указание 'Reflect.getOwnPropertyDescriptor()'. Каким образом это лучше, чем 'Object.hasOwnProperty.call (obj, prop)'? – niry

0

Любой встроенный может быть преодолено в JS - это обычно считается наилучшей практики, чтобы избежать отвергая любые нативные методы, где это возможное. Если исходная функциональность сохранена, она в порядке, так как она по-прежнему будет вести себя так, как ожидалось, и даже может быть продолжена, если она снова будет переопределена.

Поскольку это считается лучшей практикой, я рекомендую либо переназначить ключи, чтобы избежать их переопределения. Если переназначение ключей не является вариантом, вы можете заставить его чувствовать себя немного менее беспорядочным либо путем локального ссылки/упаковки Object.hasOwnProperty, либо Object.prototype.hasOwnProperty. В случае hasOwnProperty вы могли бы реализовать итератор (поскольку итерация по перечислимым не унаследованным свойствам является очень распространенным методом hasOwnProperty), чтобы уменьшить вероятность его использования. Всегда есть риск того, что кто-то менее знаком с вашим объектом, пытающимся напрямую перебирать, поэтому я действительно чувствую, что сопоставление клавиш является более безопасной ставкой, даже если это вызывает небольшую разницу между серверными ключами и локальными.

Ключ отображение может быть как простой, как суффикс, используя hasOwnProperty_data вместо hasOwnProperty это будет означать объекты будут вести себя, как и ожидалось, и автозаполнения вашего IDE, вероятно, все еще будет достаточно близко, чтобы знать, что представляет собой свойство.

Функция отображения может выглядеть следующим образом:

function remapKeys(myObj){ 
 
    for(var key in myObj){ 
 
     if(Object.prototype.hasOwnProperty.call(myObj, key)){  
 
     if((key in Object) && Object[key] !== myObj[key]){ // Check key is present on Object and that it's different ie an overridden property 
 
      myObj[key + "_data"] = myObj[key]; 
 
      delete myObj[key]; // Remove the key 
 
     } 
 
     } 
 
    } 
 
    return myObj; // Alters the object directly so no need to return but safer 
 
} 
 

 
// Test 
 
var a = {}; 
 
a.hasOwnProperty = function(){ return 'overridden'; }; 
 
a.otherProp = 'test'; 
 
remapKeys(a); 
 
console.log(a); // a { hasOwnProperty_data : function(){ return 'overridden';}, otherProp: 'test' } 
 
console.log(a.hasOwnProperty('otherProp')); // true

+0

Это похоже на много накладных расходов (память и код), чтобы избежать перезаписи встроенных методов. Я бы предпочел убедиться, что у него вообще нет метода с 'Object.create (null)' – niry

+0

Вам нужны только первые 11 строк, и вы запускаете его только один раз после загрузки ваших данных. Объем памяти для этого был бы минимальным, он изменяет объект на месте, он не клонирует его и т. Д. Я думаю, что это небольшая цена за доступ к встроенным функциям и избежание путаницы. Единственными соображениями, которые, как я считаю, мой пример не обрабатывается, являются вложенные объекты - рефакторинг для использования рекурсии будет обрабатывать их. Во-вторых, может быть полезно иметь «пользовательские сопоставления», а не просто добавлять суффикс. Создание объекта с нулевым прототипом может быть столь же запутанным, как переопределение встроенных модулей. – Brian

Смежные вопросы