Незначительный недостаток с использованием прототипического наследования Crockford - PullRequest
8 голосов
/ 10 ноября 2011

Просто экспериментируя с различными методами наследования в JS, вы столкнулись с чем-то слегка смущающим в паттерне наследования прототипа Крокфорда:

function object(o) {
    function F() {}
    F.prototype = o;
    return new F();
}

var C,
    P = {
         foo:'bar',
         baz: function(){ alert("bang"); }
         }

C = object(P);

Все хорошо - , за исключением , когда вы входите в консоль -объект отображается как F. Я видел классическую эмуляцию, в которой вы можете переопределить конструктор - есть ли подобный метод для приведения ссылки на объекты (консоль)?

Ответы [ 2 ]

13 голосов
/ 10 ноября 2011

Проблема в том, что он ссылается на name функции конструктора. Это быстро превращается в обсуждение выражений функций и операторов, а также свойства name. Оказывается, совершенно невозможно создать новую именованную функцию во время выполнения без использования eval. Имена могут быть указаны только с помощью оператора функции function fnName(){}, и невозможно динамически создать этот кусок кода, кроме его подтверждения. var fnExpression = function(){} приводит к анонимной функции, назначенной переменной. Свойство name функций является неизменным, поэтому сделка завершена. Использование Function("arg1", "arg2", "return 'fn body';") также может создать анонимную функцию, несмотря на то, что она похожа на eval.

Это в основном просто упущение в спецификации JS (Брендан Эйх заявил, что сожалеет об определении отображаемого имени так, как он это сделал 10 или около того лет назад), и решение для ES6 обсуждается. Это привело бы к большей семантике для получения отображаемого имени функции для инструментов отладки или, возможно, к явному способу ее установки и настройки.

Пока у вас есть один маршрут: eval или какая-либо другая форма позднего выполнения настраиваемого кода. (eval под любым другим именем ...)

function displayName(name, o){
  var F = eval("1&&function "+name+"(){}");
  F.prototype = o; 
  return new F;
}

Один только оператор функции не вернется из eval, но выполнение 1 && fnStatement приводит вещь в выражение, которое можно вернуть.

(Прокси-серверы Harmony также позволяют настраивать функции, которые сообщают имена, которые вы можете настраивать без eval, но которые в настоящее время недоступны, за исключением Node.js и Firefox).

Я отмечу здесь, что все те «злые» функции, которые были подняты Крокфордом и многими другими, ВСЕ имеют свое место. eval, with, расширение нативов позволяет использовать определенные методы, которые в противном случае совершенно невозможны, и их использование не является неправильным, когда есть повод. Вполне вероятно, что большинство людей не способны судить о том, когда это время подходит. По моему мнению, использование eval безвредно, чтобы компенсировать плохую семантику языка и инструменты во время ожидания решения, является вполне приемлемым и не причинит вам никакого вреда, если вы не вкладываете произвольный код в это утверждение eval.

0 голосов
/ 06 марта 2012

Если я регистрирую объект, я вижу: Object { foo="bar", baz=function()}, поэтому я не понимаю вашу проблему ...

В любом случае, можно использовать Object.create () вместо функции Крокфорда:

var P = {
         foo:'bar',
         baz: function(){ alert("bang"); }
         }

var C = Object.create (P);

console.log (C):

Object { foo="bar", baz=function()}

...