Эта статья синхронно распространяется в моемGithubначальство
Эта статья не будет слишком углубляться в основы, а вместо этого сосредоточится на трудностях прототипирования.
Вы можете сначала внимательно проанализировать картинку, а потом давайте вводить тему
prototype
Сначала давайте представимprototype
Атрибуты. Это явное свойство прототипа, которое есть только у функций. В основном все функции имеют это свойство, но есть одно исключение
let fun = Function.prototype.bind()
Если вы создадите функцию вышеописанным способом, вы обнаружите, что эта функция не имеетprototype
атрибут.
Как создается прототип
Это свойство создается автоматически, когда мы объявляем функцию.
function Foo() {}
И значением этого свойства является объект (он же прототип) только с одним свойствомconstructor
constructor
Соответствует конструктору, т.е.Foo
.
constructor
constructor
Это общественное свойство и не может быть перечислена. Как только мы изменили функциюprototype
, то новый объект не имеет этого свойства (конечно его можно получить через цепочку прототиповconstructor
).
Тогда у вас должен возникнуть вопрос, какая польза от этого атрибута? На самом деле это свойство можно назвать исторической проблемой, которая в большинстве случаев бесполезна.В моем понимании, я думаю, что оно имеет две функции:
- Сообщите объекту экземпляра, какая функция его построила
- Если вы хотите добавить некоторые пользовательские методы в конструкторы в некоторых библиотеках классов, вы можете передать
xx.constructor.method
расширять
_proto_
Это неявно в каждом объекте имеет свойство прототипа, указывая на создание прототипа конструктора объекта. На самом деле этот атрибут указывает на [[прототип]], но [[прототип]] внутреннее свойство, у нас не было доступа к, поэтому использовать_proto_
посещать.
Поскольку в JS нет понятия класса, для достижения аналогичного наследования через_proto_
Соединение объектов и прототипов в цепочку прототипов позволяет объектам получать доступ к свойствам, которые им не принадлежат.
экземпляр объекта_proto_
как производить
Как видно из приведенного выше рисунка, когда мы используемnew
оператор, результирующий экземпляр объекта имеет_proto_
Атрибуты.
function Foo() {}
// 这个函数是 Function 的实例对象
// function 就是一个语法糖
// 内部调用了 new Function(...)
Так что можно сказать, что вnew
В процессе добавляются новые объекты_proto_
и связан с прототипом конструктора.
новый процесс
- вновь созданный объект
- ссылка на прототип
- связать это
- вернуть новый объект
вызовnew
Вышеупомянутые четыре вещи произойдут в процессе, мы также можем попытаться реализовать одну из них самостоятельно.new
function create() {
// 创建一个空的对象
let obj = new Object()
// 获得构造函数
let Con = [].shift.call(arguments)
// 链接到原型
obj.__proto__ = Con.prototype
// 绑定 this,执行构造函数
let result = Con.apply(obj, arguments)
// 确保 new 出来的是个对象
return typeof result === 'object' ? result : obj
}
Например, объекты, оба передаются черезnew
производится, будь тоfunction Foo()
все ещеlet a = { b : 1 }
.
Для создания объекта рекомендуется использовать литеральный метод для создания объекта. потому что ты используешьnew Object()
Способ создания объекта должен быть найден слой за слоем через цепочку областей видимости.Object
, но то, как вы используете литералы, не имеет этой проблемы.
function Foo() {}
// function 就是个语法糖
// 内部等同于 new Function()
let a = { b: 1 }
// 这个字面量内部也是使用了 new Object()
Function.proto === Function.prototype
Для объектов,xx.__proto__.contrcutor
является конструктором объекта, но на рисунке мы можем найтиFunction.__proto__ === Function.prototype
, значит ли это, чтоFunction
произвел сам?
Ответ определенно нет. Чтобы объяснить эту проблему, мы сначала начнем сObject
Говоря о.
Из рисунка видно, что все объекты в конечном итоге можно найти через цепочку прототипов.Object.prototype
,Несмотря на то чтоObject.prototype
тоже объект, но этот объект неObject
создается самим двигателемObject.prototype
.Таким образом, можно сказать, что все экземпляры являются объектами, но объекты не обязательно являются всеми экземплярами.
Далее мы смотрим наFunction.prototype
Этот специальный объект, если вы распечатаете этот объект в браузере, вы обнаружите, что этот объект на самом деле является функцией.
Мы знаем, что функции передаются черезnew Function()
генерируется, что лиFunction.prototype
также черезnew Function()
производится? Ответа тоже нет, эта функция тоже создается самим движком. Сначала создается двигательObject.prototype
, затем созданFunction.prototype
, и через__proto__
Соедините два. Вот также хорошее объяснение одной из вышеперечисленных проблем, почемуlet fun = Function.prototype.bind()
нетprototype
Атрибуты. так какFunction.prototype
Это объект, созданный движком, движок считает, что к этому объекту добавлять ничего не нужно.prototype
Атрибуты.
Таким образом, можно сделать вывод, что не все функцииnew Function()
произведено.
имеютFunction.prototype
только позжеfunction Function()
, а затем другие конструкторыfunction Function()
Сгенерировано.
теперь могу объяснитьFunction.__proto__ === Function.prototype
Эта проблема. потому что первыйFunction.prototype
позжеfunction Function()
, так что парадокса курицы и яйца нет. почемуFunction.__proto__
будет равноFunction.prototype
, личное понимание таково: все остальные конструкторы можно найти через цепочку прототиповFunction.prototype
,иfunction Function()
Суть это тоже функция, чтобы не вводить в заблуждениеfunction Function()
из__proto__
связалсяFunction.prototype
начальство.
Суммировать
-
Object
папа всех объектов, все объекты могут проходить через__proto__
Найди это -
Function
является папой всех функций, и все функции могут быть переданы через__proto__
Найди это -
Function.prototype
иObject.prototype
это два специальных объекта, которые создаются движком - За исключением двух указанных выше специальных объектов, другие объекты передаются через конструктор.
new
от - функциональный
prototype
объект, прототип - объект
__proto__
указать на прототип,__proto__
Соединение объектов и прототипов образует цепочку прототипов.