Характеристики и цепочка прототипов функций JavaScript

JavaScript
Характеристики и цепочка прототипов функций JavaScript

вступительное предложение

На этот раз я расскажу вам о взаимосвязи между функциями JavaScript и цепочками прототипов. Я начну с функций и расскажу о том, как выглядит вся цепочка прототипов. Надеюсь, это поможет вам.

Компаньон:"Небольшие заметки о принципах JavaScript", Если у вас остались сомнения после прочтения этой статьи, вы можете продолжить чтение этой сопутствующей статьи.

Три способа использования функций

Есть примерно три способа использования функций в JavaScript:

1. Используйте его как обычную функцию

Например

// 定义函数
function foo() {}
// 调用函数
foo();

Во-вторых, в качестве конструктора для использования

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

Например

// 按照惯例,作为构造函数的函数名首字母需要大写
function Foo() {}
const obj = new Foo();

В это время для объекта obj функция Foo вызывается его конструктором.

3. Использовать как объект

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

Например

function foo() {}
foo.name = 'tom';
foo['age'] = 20;

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

проблема бронирования

Прежде чем говорить о следующем контенте, давайте рассмотрим несколько вопросов:

// 首先,定义一个函数,将会作为构造函数
function Foo() {}

// 实例化出来一个对象
const obj = new Foo();

// 在 Object 的原型上定义一个属性:objProp
Object.prototype.objProp = '我是 Object 原型上的属性';

// 在 Function 的原型上定义一个属性:funcProp
Function.prototype.funcProp = '我是 Function 原型上的属性';

// 你预想一下,以下这些分别会输出什么?
console.log(obj.objProp) // ?
console.log(obj.funcProp) // ?

console.log(Foo.objProp) // ?
console.log(Foo.funcProp) // ?

console.log(Object.objProp) // ?
console.log(Object.funcProp) // ?

console.log(Function.objProp) // ?
console.log(Function.funcProp) // ?

console.log(Array.objProp) // ?
console.log(Array.funcProp) // ?

Конструктор

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

Создание объектов с помощью нового оператора

Когда мы используем новый оператор для создания объекта из конструктора, мы проходим следующие шаги:

  1. Создайте пустой объект:{}.
  2. поместите этот пустой объект в цепочку прототипов__proto__Указатель на прототип объекта конструктора.
  3. Вызовите конструктор с новым объектом в качестве контекста, т.е. привяжитеthis, чтобы новый объект мог получить доступ к свойствам в конструкторе.
  4. Если функция не возвращает объект, возвращается этот новый объект.

Текстовое описание не просто для понимания, давайте опишем его кодом, а потом сравним:

// 新建一个构造函数
function Foo() {}
// 使用 new 操作符实例化一个对象
const obj_foo = new Foo()
// ========创建对象的过程:
// 1. 创建一个空对象:`{}`。
const obj = {};
// 2. 原型链的链接过程
obj.__proto__ = Foo.prototype;
// 3. 把新对象作为函数的上下文,即绑定 this
Foo.apply(obj, arguments);
// 4. 因为 Foo 没有返回对象,所以就返回这个新对象
return obj;
// ========END
// 这时 obj_foo 就是返回出来的新对象了

__proto__что это такое?

Сначала вы должны помнить:Только объекты будут иметь__proro__это свойство. Это ключ к js для реализации цепочки прототипов, потому что онУказатель на объект-прототип конструктора, т.е.prototypeобъект на имущество, а конструктор объекта-прототипа__proto__Он снова указывает на верхний уровень, а именно:构造函数.prototype.__proto__ -> 上一级构造函数.prototypeи так далее, чтобы сформировать то, что мы называем цепочкой прототипов. Если вы не понимаете, пожалуйста, продолжайте читать ниже:

Что такое прототип?

упоминалось ранее构造函数.prototype, это свойствоконкретная функцияСвойство , это объект-прототип конструктора, и все объекты, созданные из него, наследуют свойства и методы этого объекта-прототипа (см. MDN: JavaScript — это язык, основанный на прототипах, и каждый объект имеет объект-прототип, объект берет свой прототип в качестве шаблона, наследует методы и свойства от прототипа). Как и в предыдущем примере:const obj_foo = new Foo(), объект-прототип obj_foo является прототипом функции Foo, которая его создала, а obj_foo является производным отFoo.prototypeУнаследованные методы и свойства.

и потому, что构造函数.prototypeявляется объектом, поэтому он будет иметь__proto__Это свойство указывает на то, что объект-прототип также создается конструктором, а именно:构造函数.prototype.__proto__ -> 上一级构造函数.prototype.

Вы можете понять это__proto__Связь между , прототипом и цепочкой прототипов, именно благодаря им JavaScript может реализовать цепочку прототипов.


специальный конструктор

Давайте рассмотрим некоторые встроенные конструкторы в JavaScript, такие как:Object,Function,Number,Array,StringЖдать.

Поскольку это конструктор, его можно использовать для создания таких объектов, как:

var a = new Number('123'); // a === 123 is false
// 因为 Number.prototype 上有 toString() 方法,于是 a 也就继承了该方法:
a.toString(); // a === '123' is true
var b = new String(123); // b === '123' is false
a instanceof Number; // is true
b instanceof String; // is true

С приведенными выше впечатлениями я объясню вам два самых основных и специальных конструктора:Objectа такжеFunction.

Конструктор объектов

Используется для создания объектов, например:

const obj = new Object();

В дополнение к функции-конструктору, которую можно использовать для создания объектов, Object также имеет очень важную базовую способность:Получить все остальные конструкторы.

Здесь используется слово «производный», и он рассматривается как базовый класс или родительский класс в понимании.

То есть:Все остальные конструкторы являются производными от конструктора объекта (подклассы)..

Объясните с помощью кода (Примечание: в JavaScript нет явного понятия класса):

// 父类 Object
class Object {}
// 子类 MyFunction
class MyFunction extends Object {}

Поскольку он создан из Object, цепочка прототипов конструктора указывает на объект-прототип Object (обратитесь ко второму шагу new для понимания):

所有构造函数.prototype.__proto__ === Object.prototype

фокус

Поскольку функция также является конструктором, ее можно вывести:

Function.prototype.__proto__ === Object.prototype

Конструктор функций

Используется для создания функциональных объектов, например:

const sum = new Function('a', 'b', 'return a + b');
sum instanceof Function; // true

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

Нам не сложно придумать:Все функциональные объекты построены из Function

Доказывать:sum.__proto__ === Function.prototype

фокус

Далее можно сделать вывод, что:Object.__proto__ === Function.prototype

резюме этапа

  1. Существует три формы функций: обычные функции, конструкторы и функциональные объекты;
  2. Когда конструктор вызывается с оператором new, создается новый объект;
  3. __proto__Это свойство есть только у объектов, которое указывает на объект-прототип конструктора объекта;
  4. прототип — объект-прототип конструктора;
  5. Все конструкторы создаются из Object;
  6. Все функциональные объекты создаются функцией.

Как функции определяют форму

Ранее мы говорили о конструкторах и объектах-функциях, так как же функция определяет окончательную форму? Ответ: при использовании.

Используйте new для его вызова, тогда это конструктор, который может создать объект, если вы используете точку или скобки для его вызова, то он снова становится объектом (Примечание: исключитьprototypeАтрибуты).

Я отметил две ключевые формулы в начале:

// 1
Function.prototype.__proto__ === Object.prototype
// 2
Object.__proto__ === Function.prototype

Чтобы объяснить еще раз:

1. см.Function.prototypeЭто означает, что функция в настоящее время используется в качестве конструктора, как упоминалось ранее, все конструкторы создаются из объекта.

2. см.Object.__proto__Это означает, что в настоящее время объект используется как объект.Как упоминалось ранее, все объекты функций создаются функцией.

Отношения между Объектом и Функцией очень особенные и могут взаимно генерироваться в соответствии с различными формами.

Решить проблемы с бронированием

Теперь мы можем решить проблему резервирования.

// 首先,定义一个函数,将会作为构造函数
function Foo() {}

// 实例化出来一个对象
const obj = new Foo();

// 在 Object 的原型上定义一个属性:objProp
Object.prototype.objProp = '我是 Object 原型上的属性';

// 在 Function 的原型上定义一个属性:funcProp
Function.prototype.funcProp = '我是 Function 原型上的属性';

вопрос:

1,

console.log(obj.objProp) // ?

Отвечать:

  1. Поскольку цепочка прототипов объекта указывает на объект-прототип конструктора, поэтому:obj.__proto__ -> Foo.prototype,
  2. Поскольку все конструкторы являются производными от Object, поэтому:Foo.prototype.__proto__ -> Object.prototype
  3. потому чтоObject.prototypeВ этом свойстве есть objProp, поэтому obj.objProp === 'Я являюсь свойством прототипа объекта'

2,

console.log(obj.funcProp) // ?

Отвечать:

  1. Поскольку цепочка прототипов объекта указывает на объект-прототип конструктора, поэтому:obj.__proto__ -> Foo.prototype,
  2. Поскольку все конструкторы являются производными от Object, поэтому:Foo.prototype.__proto__ -> Object.prototype
  3. из-заObject.prototypeНе могу найти свойство funcProp, продолжаем искать по цепочке прототипов:Object.prototype.__proto__ -> null
  4. не найдено, вернуть undefined

3.

console.log(Foo.objProp) // ?

Отвечать:

  1. Foo.objPropзаключается в использовании Foo в качестве объекта, в настоящее время это объект функции, поэтому он создается с помощью функции:Foo.__proto__ -> Function.prototype
  2. из-заFunction.prototypeНе могу найти свойство objProp, продолжаем искать по цепочке прототипов:Function.prototype.__proto__ -> Object.prototype
  3. существуетObject.prototypeСвойство objProp находится в Foo.objProp === 'Я являюсь свойством прототипа объекта'

4.

console.log(Foo.funcProp) // ?

Отвечать:

  1. Foo.funcPropзаключается в использовании Foo в качестве объекта, в настоящее время это объект функции, поэтому он создается с помощью функции:Foo.__proto__ -> Function.prototype
  2. существуетFunction.prototypeСвойство funcProp находится в Foo.funcProp === 'Я являюсь свойством прототипа функции'

5.

console.log(Object.objProp) // ?

Отвечать:

  1. Object.objPropОбъект используется как объект, в настоящее время это объект функции, поэтому он создается функцией:Object.__proto__ -> Function.prototype
  2. существуетFunction.prototypeНе могу найти свойство objProp, продолжаем искать по цепочке прототипов:Function.prototype.__proto__ -> Object.prototype
  3. существуетObject.prototypeСвойство objProp находится в объекте, поэтому Object.objProp === 'Я являюсь свойством прототипа объекта'

6.

console.log(Object.funcProp) // ?

Отвечать:

  1. Object.funcPropЭто использование Object в качестве объекта.В настоящее время это функциональный объект, поэтому он создается с помощью функции:Object.__proto__ -> Function.prototype
  2. существуетFunction.prototypeСвойство funcProp находится в , поэтому Object.funcProp === 'Я являюсь свойством прототипа функции'

7.

console.log(Function.objProp) // ?

Примечание. Во избежание путаницы Функция означает объект, а %Function означает конструктор.

Отвечать:

  1. Function.objPropФункция используется как объект, в настоящее время это объект функции, поэтому он создается с помощью %Function:Function.__proto__ -> %Function.prototype
  2. существует%Function.prototypeНе могу найти свойство objProp, продолжаем искать по цепочке прототипов:%Function.prototype.__proto__ -> Object.prototype
  3. существуетObject.prototypeСвойство objProp находится в , поэтому Function.objProp === 'Я являюсь свойством прототипа объекта'

8,

console.log(Function.funcProp) // ?

Отвечать:

  1. Function.funcPropФункция используется как объект, в настоящее время это объект функции, поэтому он создается с помощью $Function:Function.__proto__ -> %Function.prototype
  2. существует%Function.prototypeСвойство funcProp находится в функции, поэтому Function.funcProp === 'Я являюсь свойством прототипа функции'

9,

console.log(Array.objProp) // ?

Ответ: Попробуйте проанализировать сами, добро пожаловать в поле для комментариев.

10.

console.log(Array.funcProp) // ?

Ответ: Попробуйте проанализировать сами, добро пожаловать в поле для комментариев.

Изображение прототипа цепи

Я нарисовал цепочку прототипов для справки, чтобы сравнить описанный выше процесс:

Если в этой статье есть какие-либо ошибки, пожалуйста, помогите указать, я буду продолжать совершенствоваться.


обновить запись

12-05: реорганизована структура контента, исправлены текстовые ошибки и оптимизировано изображение цепочки прототипов.