Подтвердить что ты не робот

Возможно ли создать скрытое свойство в javascript

Я хочу создать объект со скрытым свойством (свойство, которое не отображается в цикле for (var x in obj). Можно ли это сделать?

4b9b3361

Ответ 1

Это невозможно в ECMAScript 3 (именно это были основные браузеры, реализованные в то время, когда этот вопрос задавался в 2010 году). Однако в ECMAScript 5, который реализуют текущие версии всех основных браузеров, можно установить свойство как не перечисляемое:

var obj = {
   name: "Fred"
};

Object.defineProperty(obj, "age", {
    enumerable: false,
    writable: true
});

obj.age = 75;

/* The following will only log "name=>Fred" */
for (var i in obj) {
   console.log(i + "=>" + obj[i]);
}

Это работает в текущих браузерах: см. Http://kangax.github.com/es5-compat-table/ для деталей о совместимости в старых браузерах.

Обратите внимание, что свойство также должно быть доступно для записи в вызове Object.defineProperty чтобы разрешить обычные назначения (по умолчанию это false).

Ответ 2

Это немного сложно!

function secret() {
  var cache = {};
  return function(){
    if (arguments.length == 1) { return cache[arguments[0]];}
    if (arguments.length == 2) { cache[arguments[0]] = arguments[1]; }
  };
}
var a = secret();

a.hello = 'world';
a('hidden', 'from the world');

Если вы настоящий профессионал, вы можете сделать это таким образом!

var a = new (secret())();

a.hello = 'world';
a.constructor('hidden', 'from the world');

Теперь, если вы посмотрите в firebug, это будет объект... но вы знаете лучше!;-)

Ответ 3

Чтобы держать вещи в актуальном состоянии, это положение вещей в ES6+. Я немного выйду за рамки вопроса и расскажу о том, как скрыть свойства вообще, а не только из цикла for... in.

Есть несколько способов создать то, что можно назвать "скрытыми свойствами", не рассматривая такие вещи, как переменные, закрытые замыканиями, которые ограничены правилами области видимости.

Теперь-классика, не перечисляемая собственность

Как и в предыдущих версиях ECMAScript, вы можете использовать Object.defineProperty для создания свойств, которые не помечены как enumerable. Это делает свойство не отображаемым, когда вы перечисляете свойства объекта с помощью определенных методов, таких как цикл for... in и функция Object.keys.

Object.defineProperty(myObject, "meaning of life", {
    enumerable : false,
    value : 42
});

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

(Не перечисляемое) свойство symbol

В ES6 можно создавать свойства с ключами нового примитивного типа - symbol. Этот тип используется самим Javascript для перечисления объекта с помощью цикла for... of и авторами библиотек для выполнения любых других задач.

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

Вы создаете symbol используя функцию Symbol:

let symb = Symbol("descriptive text");

Вы можете использовать функцию Object.defineProperty для определения свойств с символами в качестве ключей.

let theSecretKey = Symbol("meaning of life");
Object.defineProperty(myObject, theSecretKey, {
    enumerable : false,
    value : 42
});

Если кто-то не получит ссылку на этот точный символьный объект, он не сможет найти значение свойства по ключу.

Но вы также можете использовать обычный синтаксис:

let theSecretKey = Symbol("meaning of life");
myObject[theSecretKey] = 42;

Свойства с этим типом ключа никогда не будут отображаться for... in циклах for... in и т.п., Но все же могут быть перечисляемыми и не перечисляемыми, поскольку функции, такие как Object.assign работают по-другому для не перечислимых свойств.

Object.getOwnPropertyNames не получит вам symbol ключи объекта, но с таким же именем Object.getOwnPropertySymbols добьется Object.getOwnPropertySymbols.

Слабые карты

Самый надежный способ скрыть свойство объекта - не хранить его вообще на объекте. До ES6 это было довольно сложно сделать, но теперь у нас слабые карты.

Слабая карта - это, в основном, Map, то есть хранилище значений ключей, которое не хранит (сильные) ссылки на ключи, чтобы их можно было собирать мусором. Слабая карта очень ограничена и не позволяет перечислять ее ключи (это сделано по замыслу). Однако, если вы получите ссылку на один из ключей карты, вы можете получить значение, соответствующее ему.

Они в первую очередь предназначены для расширения объектов без их реального изменения.

Основная идея - создать слабую карту:

let weakMap = new WeakMap();

И используйте объекты, которые вы хотите расширить в качестве ключей. Тогда значениями будут наборы свойств, либо в форме объектов {}, либо в форме структур данных Map.

weakMap.set(myObject, {
    "meaning of life" : 42
});

Преимущество этого подхода в том, что кто-то должен получить ссылку на ваш экземпляр weakMap и ключ для того, чтобы вывести значения, или даже знать, что они существуют. weakMap это невозможно. Так что это 100%, гарантированно будет в безопасности. Скрытие свойств таким образом гарантирует, что ни один пользователь никогда не обнаружит их, а ваше веб-приложение никогда не будет взломано *

Самым большим недостатком во всем этом, конечно, является то, что это не создает фактическую собственность. Так что он не участвует в цепочке прототипов и тому подобное.

(*) Это ложь.

Ответ 4

var Foo=function(s){
    var hidden
    this.setName=function(name){theName=name}
    this.toString=function(){return theName}
    this.public=s
}
var X=new Foo('The X')
X.setName('This is X')
X // returns 'This is X'
X.public // returns 'The X'
X.hidden // returns 'undefined'

Ответ 5

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

Object.defineProperty(
    objectName,
    'propertiesName', {
        enumerable: false
    }
)