Использование «Object.create» вместо «new» - PullRequest
355 голосов
/ 25 апреля 2010

Javascript 1.9.3 / ECMAScript 5 представляет Object.create, который Дуглас Крокфорд среди других защищал в течение длительного времени. Как заменить new в приведенном ниже коде на Object.create?

var UserA = function(nameParam) {
    this.id = MY_GLOBAL.nextId();
    this.name = nameParam;
}
UserA.prototype.sayHello = function() {
    console.log('Hello '+ this.name);
}
var bob = new UserA('bob');
bob.sayHello();

(Предположим, MY_GLOBAL.nextId существует).

Лучшее, что я могу придумать, это:

var userB = {
    init: function(nameParam) {
        this.id = MY_GLOBAL.nextId();
        this.name = nameParam;
    },
    sayHello: function() {
        console.log('Hello '+ this.name);
    }
};
var bob = Object.create(userB);
bob.init('Bob');
bob.sayHello();

Кажется, что нет никакого преимущества, поэтому я думаю, что я не получаю его. Я, наверное, слишком неоклассичен. Как мне использовать Object.create для создания пользователя 'bob'?

Ответы [ 14 ]

2 голосов
/ 01 февраля 2018

В то время как Дуглас Крокфорд был ревностным сторонником Object.create (), и он, по сути, является причиной того, почему эта конструкция фактически присутствует в javascript, у него больше нет такого мнения.

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

Вы можете посмотреть это видео 2014 года, где он говорит на Nordic.js:

https://www.youtube.com/watch?v=PSGEjv3Tqo0

enter image description here

2 голосов
/ 26 апреля 2010

Вы должны сделать пользовательскую функцию Object.create(). Тот, который решает проблемы Crockfords, а также вызывает вашу функцию инициализации.

Это будет работать:

var userBPrototype = {
    init: function(nameParam) {
        this.name = nameParam;
    },
    sayHello: function() {
        console.log('Hello '+ this.name);
    }
};


function UserB(name) {
    function F() {};
    F.prototype = userBPrototype;
    var f = new F;
    f.init(name);
    return f;
}

var bob = UserB('bob');
bob.sayHello();

Здесь UserB похож на Object.create, но с учетом наших потребностей.

Если вы хотите, вы также можете позвонить:

var bob = new UserB('bob');
1 голос
/ 19 августа 2018

Резюме:

  • Object.create() - это функция Javascript, которая принимает 2 аргумента и возвращает новый объект.
  • Первый аргумент - это объект, который будет прототипом вновь созданного объекта
  • Второй аргумент - это объект, который будет свойствами вновь созданного объекта

Пример:

const proto = {
  talk : () => console.log('hi')
}

const props = {
  age: {
    writable: true,
    configurable: true,
    value: 26
  }
}


let Person = Object.create(proto, props)

console.log(Person.age);
Person.talk();

Практические применения:

  1. Основным преимуществом создания объекта таким способом является то, что прототип может быть явно определен . При использовании литерала объекта или ключевого слова new вы не можете это контролировать (однако вы можете перезаписать их, разумеется).
  2. Если мы хотим получить прототип, ключевое слово new вызывает функцию конструктора. С Object.create() нет необходимости вызывать или даже объявлять функцию конструктора .
  3. Это может быть полезным инструментом, когда вы хотите создавать объекты очень динамично. Мы можем создать функцию фабрики объектов, которая создает объекты с разными прототипами в зависимости от полученных аргументов.
1 голос
/ 08 февраля 2018

Я предпочитаю закрытый подход.

Я все еще использую new. Я не использую Object.create. Я не использую this.

Я все еще использую new, поскольку мне нравится его декларативный характер.

Рассмотрим это для простого наследования.

window.Quad = (function() {

    function Quad() {

        const wheels = 4;
        const drivingWheels = 2;

        let motorSize = 0;

        function setMotorSize(_) {
            motorSize = _;
        }

        function getMotorSize() {
            return motorSize;
        }

        function getWheelCount() {
            return wheels;
        }

        function getDrivingWheelCount() {
            return drivingWheels;
        }
        return Object.freeze({
            getWheelCount,
            getDrivingWheelCount,
            getMotorSize,
            setMotorSize
        });
    }

    return Object.freeze(Quad);
})();

window.Car4wd = (function() {

    function Car4wd() {
        const quad = new Quad();

        const spareWheels = 1;
        const extraDrivingWheels = 2;

        function getSpareWheelCount() {
            return spareWheels;
        }

        function getDrivingWheelCount() {
            return quad.getDrivingWheelCount() + extraDrivingWheels;
        }

        return Object.freeze(Object.assign({}, quad, {
            getSpareWheelCount,
            getDrivingWheelCount
        }));
    }

    return Object.freeze(Car4wd);
})();

let myQuad = new Quad();
let myCar = new Car4wd();
console.log(myQuad.getWheelCount()); // 4
console.log(myQuad.getDrivingWheelCount()); // 2
console.log(myCar.getWheelCount()); // 4
console.log(myCar.getDrivingWheelCount()); // 4 - The overridden method is called
console.log(myCar.getSpareWheelCount()); // 1

Обратная связь приветствуется.

...