Как передать свойство javascript (имя) без использования жестко закодированной строки? - PullRequest
0 голосов
/ 05 сентября 2018

Пример использования:

  1. У меня есть объект с атрибутом "myProperty", имеющий getter и setter (поддерживаются "Getter and Setters свойства", так как EcmaScript 5: https://www.w3schools.com/js/js_es5.asp):

    var obj = {
      myProperty:'myPropertyValue', 
      get myProperty(){
        return this.property;
      },
      set myProperty(value){
        this.property=value;
      }
    };
    
  2. Я хотел бы привязать этот атрибут к представлению, которое является задачей пользовательской функции, которая называется bindProperty.

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

bindProperty(obj, 'myProperty');

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

Если бы я использовал

bindProperty(obj, obj.myProperty);

функция будет знать только значение свойства 'myPropertyValue', а не откуда оно берется.

=> Как я могу передать / идентифицировать само свойство без использования строки?

A. Используя отражение?

Я мог бы представить что-то вроде

bindProperty(obj, ()=>obj.myProperty);

Функция bindProperty затем должна будет выполнить некоторую магию отражения , чтобы узнать имя атрибута в теле лямбда-выражения (псевдокод):

let attributeName = getNameofArgumentFromBodyOfLambdaExpression(lambda);
obj[attributeName] = 'newValue';

=> Возможно ли в JavaScript оценить тело лямбда-выражения, используя отражение, чтобы получить имя свойства?

(я знаю, что это можно сделать на языках .NET, например,

Private Sub BindProperty(Of T)(propertyExpression As Expression(Of Func(Of T)))

    Dim propertyName As String = GetPropertyName(propertyExpression)
'...

)

B. Использование сложных атрибутов

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

obj.myProperty.set('newValue')

или

obj.myProperty('newValue')  //similar to knockout observables

Я все еще хочу иметь возможность использовать отличную функцию Getter / Setter. Другими словами: я хочу использовать свои свойства как простые атрибуты:

obj.myProperty = 'newValue'

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

C. Любые другие альтернативы?

Ответы [ 2 ]

0 голосов
/ 05 сентября 2018

Я только что нашел следующую простую работу, которая может полностью удовлетворить мои потребности:

function bindProperty(obj, lambdaExpression){

 let expression = lambdaExpression.toString();  // "()=> obj.myProperty"
 let subStrings = expression.split(".");
 let propertyName = subStrings[1]; 

 console.info(propertyName );
 //...

}
0 голосов
/ 05 сентября 2018

Объект в javascript - это более или менее просто отображение строк или символов в значениях. Нет реального отражения, к которому можно обратиться в среде выполнения, которое позволило бы вам вернуться назад от значения к имени свойства.

Если все, что вам нужно, это рефакторинг, один из способов сделать это - просто настроить вашу IDE для распознавания строковых методов доступа, предоставив некоторую информацию о типе через Flow или Typescript или что-то в этом роде (информация о типе вероятна что позволяет отражению работать в таких языках, как .NET). Или вы можете просто выбрать уникальный префикс, такой как «viewable_propName», и просто выполнить поиск и замену, если вам нужно переименовать.

Если вы действительно сосредоточены на том, чтобы заставить это работать без информации о типе и в текущем синтаксисе ES6, вы можете сделать следующее:

function getNameofPropFromVal(obj, val){
    for(let prop in obj){
       if(obj[prop] === val) return prop;
    }
}

obj[getNameofPropFromVal(obj, obj.myProp)] = 'newVal';

Хотя это имеет недостатки: (1) Нет гарантии, что два свойства не будут иметь одинаковое значение. (2) Это приводит к ненужным накладным расходам во время выполнения.

Наконец, если вы хотите быть передовым и использовать такой трансформатор, как babel, вы можете использовать декораторы для вашего bindProperty метода. Таким образом, вы можете просто выполнить привязку в самом определении объекта. Вот статья , объясняющая суть, а вот более формальное предложение ECMAScript .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...