Существуют ли эффективные способы использования `__proto__` или` setPrototypeOf() `в javascript?

MDN имеет огромное страшное предупреждение о модификации прототипа в вашем коде:

Изменение [[Prototype]] объекта по характеру современные JavaScript-движки оптимизируют доступ к ресурсам, очень медленно в каждом браузере и движке JavaScript. Влияние на исполнение измененного наследования является тонким и отдаленным, и не ограничиваясь просто временем, проведенным в obj. proto =... statement, но может распространяться на любой код, который имеет доступ к любому объекту, [[Прототип]] изменен. Если вы заботитесь о производительности, следует избегать установки [[Prototype]] объекта. Вместо этого создайте новый объект с желаемым [[Prototype]] с использованием Object.create().

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/setPrototypeOf.

Мне интересно, есть ли ситуации, в которых вы можете изменить прототип объекта, не вызывая каскадных эффектов оптимизации, которые убивают вашу производительность программы. Похоже, должно быть. Например, если вы только модифицируете прототип сразу после создания объекта (и до его использования каким-либо другим). Но я думаю, что это очень зависит от двигателя.

Знает ли кто-нибудь, есть ли эффективные способы изменения прототипа объекта?

Изменить: мотивация для этого вопроса исходит из желания создать объекты, которые наследуют от Function. И единственный способ, которым я знаю, как это сделать, - изменить прототип функции. Посмотрите на самую нижнюю часть ответа Raynos: класс javascript наследуется от класса Function

Ответ 1

Мотивация для этого вопроса связана с желанием создать объекты, которые наследуются от функции.

Кажется, что вы пытаетесь сделать следующее:

  • Создание новых объектов
  • Установите прототип этих объектов (или свойство __proto__) для ссылки на Fuction.prototype, чтобы они наследовали свойства из Function.prototype, например:
    • .apply
    • .call
    • .bind

Вам не нужно менять прототип объектов, если вы можете правильно установить его на нужную ссылку во время создания объекта.


Ответ один: установка прототипа объекта

Вы можете установить прототип любых объектов при создании с помощью Object.create(). Обратите внимание, что назначение прототипа объекта Function.prototype не приведет к тому, что объект будет вызываемой функцией. Но если вы все еще хотите назначить прототип для ссылки на Function.prototype или на какой-либо другой объект, вы можете сделать следующее:

var obj1 = Object.create(Function.prototype);

Это будет:

  • Создайте новый объект obj1
  • Задайте свой прототип (или свойство __proto__) для ссылки на Function.prototype или любой другой объект, который вы передаете в качестве аргумента
    • то есть делегирует неудачные поиски свойств Function.prototype через цепочку прототипов (это прототип JavaScript и что __proto__ означает: место для делегирования неудачных поисков свойств)

Это не требует использования Object.setPrototypeOf() для изменения прототипа существующего объекта, поскольку он назначает прототип в момент создания объекта. Для получения дополнительных примеров и информации см. Документы MDN для Object.create() - это не несет те же страшные предупреждения, что и setPrototypeOf(). Вы можете использовать Object.create() для установки любого нового прототипа объекта.


Ответ два: функции уже являются объектами

Тем не менее, если вы хотите, чтобы объект, который ведет себя как функция, вы можете просто создать функцию. Функция все еще является объектом, но с дополнительными функциональными свойствами и поведением; вы все равно можете относиться к нему как к объекту, присваивая ему свойства. Если вы хотите создать функцию, которая также действует как объект или объект, который также может выполнять те же функции, что и функция, то функция уже делает это. Вы можете делать такие вещи, как:

var func = function() { return 'hello world'; }; // func is a function
func.property1 = 'foo'; // func is also an object
func.property2 = 'bar';

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

Ответ 2

Есть только одна причина, по которой я знаю изменить прото, когда вам нужен массив, такой как comportement.

    var class_func = { toto: function(){console.log('hi')}};
     ...
    var a = [];
    a.__proto__ = class_func 
    a.toto()
    //hi
    a[5] = 8
   // 8
    a.length
    //6

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