вступительное предложение
На этот раз я расскажу вам о взаимосвязи между функциями 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) // ?
Конструктор
Далее мы объясним вторую особенность функции, как она выглядит при использовании в качестве конструктора.
Создание объектов с помощью нового оператора
Когда мы используем новый оператор для создания объекта из конструктора, мы проходим следующие шаги:
- Создайте пустой объект:
{}
. - поместите этот пустой объект в цепочку прототипов
__proto__
Указатель на прототип объекта конструктора. - Вызовите конструктор с новым объектом в качестве контекста, т.е. привяжите
this
, чтобы новый объект мог получить доступ к свойствам в конструкторе. - Если функция не возвращает объект, возвращается этот новый объект.
Текстовое описание не просто для понимания, давайте опишем его кодом, а потом сравним:
// 新建一个构造函数
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
резюме этапа
- Существует три формы функций: обычные функции, конструкторы и функциональные объекты;
- Когда конструктор вызывается с оператором new, создается новый объект;
-
__proto__
Это свойство есть только у объектов, которое указывает на объект-прототип конструктора объекта; - прототип — объект-прототип конструктора;
- Все конструкторы создаются из Object;
- Все функциональные объекты создаются функцией.
Как функции определяют форму
Ранее мы говорили о конструкторах и объектах-функциях, так как же функция определяет окончательную форму? Ответ: при использовании.
Используйте 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) // ?
Отвечать:
- Поскольку цепочка прототипов объекта указывает на объект-прототип конструктора, поэтому:
obj.__proto__ -> Foo.prototype
,- Поскольку все конструкторы являются производными от Object, поэтому:
Foo.prototype.__proto__ -> Object.prototype
- потому что
Object.prototype
В этом свойстве есть objProp, поэтому obj.objProp === 'Я являюсь свойством прототипа объекта'
2,
console.log(obj.funcProp) // ?
Отвечать:
- Поскольку цепочка прототипов объекта указывает на объект-прототип конструктора, поэтому:
obj.__proto__ -> Foo.prototype
,- Поскольку все конструкторы являются производными от Object, поэтому:
Foo.prototype.__proto__ -> Object.prototype
- из-за
Object.prototype
Не могу найти свойство funcProp, продолжаем искать по цепочке прототипов:Object.prototype.__proto__ -> null
- не найдено, вернуть undefined
3.
console.log(Foo.objProp) // ?
Отвечать:
Foo.objProp
заключается в использовании Foo в качестве объекта, в настоящее время это объект функции, поэтому он создается с помощью функции:Foo.__proto__ -> Function.prototype
- из-за
Function.prototype
Не могу найти свойство objProp, продолжаем искать по цепочке прототипов:Function.prototype.__proto__ -> Object.prototype
- существует
Object.prototype
Свойство objProp находится в Foo.objProp === 'Я являюсь свойством прототипа объекта'
4.
console.log(Foo.funcProp) // ?
Отвечать:
Foo.funcProp
заключается в использовании Foo в качестве объекта, в настоящее время это объект функции, поэтому он создается с помощью функции:Foo.__proto__ -> Function.prototype
- существует
Function.prototype
Свойство funcProp находится в Foo.funcProp === 'Я являюсь свойством прототипа функции'
5.
console.log(Object.objProp) // ?
Отвечать:
Object.objProp
Объект используется как объект, в настоящее время это объект функции, поэтому он создается функцией:Object.__proto__ -> Function.prototype
- существует
Function.prototype
Не могу найти свойство objProp, продолжаем искать по цепочке прототипов:Function.prototype.__proto__ -> Object.prototype
- существует
Object.prototype
Свойство objProp находится в объекте, поэтому Object.objProp === 'Я являюсь свойством прототипа объекта'
6.
console.log(Object.funcProp) // ?
Отвечать:
Object.funcProp
Это использование Object в качестве объекта.В настоящее время это функциональный объект, поэтому он создается с помощью функции:Object.__proto__ -> Function.prototype
- существует
Function.prototype
Свойство funcProp находится в , поэтому Object.funcProp === 'Я являюсь свойством прототипа функции'
7.
console.log(Function.objProp) // ?
Примечание. Во избежание путаницы Функция означает объект, а %Function означает конструктор.
Отвечать:
Function.objProp
Функция используется как объект, в настоящее время это объект функции, поэтому он создается с помощью %Function:Function.__proto__ -> %Function.prototype
- существует
%Function.prototype
Не могу найти свойство objProp, продолжаем искать по цепочке прототипов:%Function.prototype.__proto__ -> Object.prototype
- существует
Object.prototype
Свойство objProp находится в , поэтому Function.objProp === 'Я являюсь свойством прототипа объекта'
8,
console.log(Function.funcProp) // ?
Отвечать:
Function.funcProp
Функция используется как объект, в настоящее время это объект функции, поэтому он создается с помощью $Function:Function.__proto__ -> %Function.prototype
- существует
%Function.prototype
Свойство funcProp находится в функции, поэтому Function.funcProp === 'Я являюсь свойством прототипа функции'
9,
console.log(Array.objProp) // ?
Ответ: Попробуйте проанализировать сами, добро пожаловать в поле для комментариев.
10.
console.log(Array.funcProp) // ?
Ответ: Попробуйте проанализировать сами, добро пожаловать в поле для комментариев.
Изображение прототипа цепи
Я нарисовал цепочку прототипов для справки, чтобы сравнить описанный выше процесс:
Если в этой статье есть какие-либо ошибки, пожалуйста, помогите указать, я буду продолжать совершенствоваться.
обновить запись
12-05: реорганизована структура контента, исправлены текстовые ошибки и оптимизировано изображение цепочки прототипов.