Поиск…


Стандартный прототип функции

Начните с определения функции Foo которую мы будем использовать в качестве конструктора.

function Foo (){}

Редактируя Foo.prototype , мы можем определить свойства и методы, которые будут использоваться всеми экземплярами Foo .

Foo.prototype.bar = function() {
  return 'I am bar';
};

Затем мы можем создать экземпляр с использованием new ключевого слова и вызвать метод.

var foo = new Foo();

console.log(foo.bar()); // logs `I am bar`

Разница между Object.key и Object.prototype.key

В отличие от языков, таких как Python, статические свойства функции конструктора не наследуются экземплярами. Экземпляры только наследуют от своего прототипа, который наследуется от прототипа родительского типа. Статические свойства никогда не наследуются.

function Foo() {};
Foo.style = 'bold';

var foo = new Foo();

console.log(Foo.style); // 'bold'
console.log(foo.style); // undefined

Foo.prototype.style = 'italic';

console.log(Foo.style); // 'bold'
console.log(foo.style); // 'italic'

Новый объект из прототипа

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

var proto = { foo: "foo", bar: () => this.foo };

var obj = Object.create(proto);

console.log(obj.foo);
console.log(obj.bar());

Консольный выход:

> "foo"
> "foo"

ПРИМЕЧАНИЕ. Object.create доступен из ECMAScript 5, но вот полиполк, если вам нужна поддержка ECMAScript 3

if (typeof Object.create !== 'function') {
    Object.create = function (o) {
        function F() {}
        F.prototype = o;
        return new F();
    };
}

Источник: http://javascript.crockford.com/prototypal.html


Object.create ()

Метод Object.create () создает новый объект с указанным объектом и свойствами прототипа.

Синтаксис: Object.create(proto[, propertiesObject])

Параметры :

  • proto (Объект, который должен быть прототипом вновь созданного объекта.)
  • propertiesObject (Необязательно. Если задано и не определено, объект, чьи перечисляемые собственные свойства (то есть те свойства, которые определены сами по себе, а не перечислимые свойства вдоль его цепи прототипов), определяют дескрипторы свойств, которые должны быть добавлены к вновь созданному объекту, с соответствующим имена свойств. Эти свойства соответствуют второму аргументу Object.defineProperties ().)

Возвращаемое значение

Новый объект с указанным объектом и свойствами прототипа.

Исключения

Исключение TypeError, если параметр proto не равен null или объекту.

Прототипное наследование

Предположим, что у нас есть простой объект, называемый prototype :

var prototype = { foo: 'foo', bar: function () { return this.foo; } };

Теперь нам нужен еще один объект, называемый obj который наследуется от prototype , что является тем же самым утверждением, что prototype является прототипом obj

var obj = Object.create(prototype);

Теперь все свойства и методы из prototype будут доступны для obj

console.log(obj.foo);
console.log(obj.bar());

Консольный выход

"foo"
"foo"

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

prototype.foo = "bar";
console.log(obj.foo);

Консольный выход

"bar"

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

Object.prototype.breakingLibraries = 'foo';
console.log(obj.breakingLibraries);
console.log(prototype.breakingLibraries);

Консольный выход

"foo"
"foo"

Интересный факт Я использовал консоль браузера, чтобы сделать эти примеры и сломал эту страницу, добавив свойство breakingLibraries .


Псевдоклассическое наследование

Это эмуляция классического наследования, использующая прототипическое наследование, которое показывает, насколько мощными прототипами. Это было сделано, чтобы сделать язык более привлекательным для программистов, поступающих с других языков.

6

ВАЖНОЕ ПРИМЕЧАНИЕ . Поскольку ES6 не имеет смысла использовать псевдокальсическое наследование, так как язык имитирует обычные классы . Если вы не используете ES6, вы должны . Если вы все еще хотите использовать классический шаблон наследования, и вы находитесь в среде ECMAScript 5 или ниже, то ваш псевдо-классический вариант - ваш лучший выбор.

«Класс» - это просто функция, которая вызывается с new операндом и используется как конструктор.

function Foo(id, name) {
    this.id = id;
    this.name = name;
}

var foo = new Foo(1, 'foo');
console.log(foo.id);

Консольный выход

1

foo - это экземпляр Foo. Соглашение о кодировании JavaScript говорит, что если функция начинается с случая с большой буквы, она может быть вызвана как конструктор (с new операндом).


Чтобы добавить свойства или методы в «класс», вы должны добавить их в свой прототип, который можно найти в свойстве prototype конструктора.

Foo.prototype.bar = 'bar';
console.log(foo.bar);

Консольный выход

бар

Фактически то, что Foo делает как «конструктор», просто создает объекты с Foo.prototype качестве прототипа.


Вы можете найти ссылку на свой конструктор на каждом объекте

console.log(foo.constructor);

функция Foo (id, name) {...

console.log({ }.constructor);

function Object () {[native code]}

А также проверьте, является ли объект экземпляром данного класса с оператором instanceof

console.log(foo instanceof Foo);

правда

console.log(foo instaceof Object);

правда

Настройка прототипа объекта

5

С помощью ES5 + функция Object.create может использоваться для создания объекта с любым другим объектом в качестве прототипа.

const anyObj = {
    hello() {
        console.log(`this.foo is ${this.foo}`);
    },
};

let objWithProto = Object.create(anyObj);
objWithProto.foo = 'bar';

objWithProto.hello(); // "this.foo is bar"

Чтобы явно создать объект без прототипа, используйте null в качестве прототипа. Это означает, что объект не будет наследовать от Object.prototype и полезен для объектов, используемых для проверки сущностей существования, например

let objInheritingObject = {};
let objInheritingNull = Object.create(null);

'toString' in objInheritingObject; // true
'toString' in objInheritingNull ; // false
6

Из ES6 прототип существующего объекта можно изменить, используя Object.setPrototypeOf , например

let obj = Object.create({foo: 'foo'});
obj = Object.setPrototypeOf(obj, {bar: 'bar'});

obj.foo; // undefined
obj.bar; // "bar"

Это можно сделать практически в любом месте, в том числе на this объекте или в конструкторе.

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

5

До ES5 единственным способом создания объекта с помощью заданного вручную прототипа было создание его с помощью new , например

var proto = {fizz: 'buzz'};

function ConstructMyObj() {}
ConstructMyObj.prototype = proto;

var objWithProto = new ConstructMyObj();
objWithProto.fizz; // "buzz"

Это поведение достаточно близко к Object.create что можно написать полипол.



Modified text is an extract of the original Stack Overflow Documentation
Лицензировано согласно CC BY-SA 3.0
Не связан с Stack Overflow