предисловие
Привет, яВакагава. Это первое из серии интервьюеров, которых попросили помочь читателям улучшить
JS
базовые знания, в том числеnew、call、apply、this、继承
связанная информация.
面试官问系列
Статья выглядит следующим образом: Заинтересованные читатели могут нажать, чтобы прочитать.
1.Интервьюер спросил: Могу ли я смоделировать новый оператор, реализующий JS?
2.Интервьюер спросил: Могу ли я смоделировать метод привязки, реализующий JS?
3.Интервьюер спросил: Могу ли я смоделировать вызов и применить методы JS?
4.Интервьюер спросил: этот пункт JS
5.Интервьюер спросил: наследование JS
использовалVuejs
Все учащиеся знают, что необходимо использоватьnew
оператор для создания экземпляра.
new Vue({
el: '#app',
mounted(){},
});
Затем интервьюер может спросить,new
Что именно он делал и как это имитировать.
Прикреплен абзац из предыдущей статьи: уже существует множество реализаций симуляции.
new
Статья об операторах, почему я должен писать ее снова. Обучение похоже на большую гору: люди взбираются на гору по разным дорогам и делятся пейзажами, которые видят. Возможно, вы не сможете увидеть пейзаж, который видят другие, и почувствовать настроение других. Только когда вы идете на гору самостоятельно, вы можете увидеть разные пейзажи и испытать более глубокие переживания.
что нового сделал
Сначала простоПример 1:
// 例子1
function Student(){
}
var student = new Student();
console.log(student); // {}
// student 是一个对象。
console.log(Object.prototype.toString.call(student)); // [object Object]
// 我们知道平时声明对象也可以用new Object(); 只是看起来更复杂
// 顺便提一下 `new Object`(不推荐)和Object()也是一样的效果
// 可以猜测内部做了一次判断,用new调用
/** if (!(this instanceof Object)) {
* return new Object();
* }
*/
var obj = new Object();
console.log(obj) // {}
console.log(Object.prototype.toString.call(student)); // [object Object]
typeof Student === 'function' // true
typeof Object === 'function' // true
Из этого примера мы видим, что функция сnew
После вызова оператора создается новый объект. иStudent
иObject
являются функциями, ноStudent
наш обычай,Object
даJS
встроенный в себя.
Давайте посмотрим на диаграмму вывода в консоль, желающие могут попробовать ее на консоли.иnew Object()
Сгенерированный объект отличаетсяnew Student()
Также есть слой вложенности в середине сгенерированного объекта__proto__
,этоconstructor
даStudent
эта функция.
// 也就是说:
student.constructor === Student;
Student.prototype.constructor === Student;
Вывод 1. Из этого простого примераnew
Оператор делает две вещи:
- Создается новый объект.
- Этот объект будет выполнен
[[Prototype]]
(это,__proto__
)Ссылка на сайт.
Далее давайте посмотрим на обновленную версиюПример 2:
// 例子2
function Student(name){
console.log('赋值前-this', this); // {}
this.name = name;
console.log('赋值后-this', this); // {name: '若川'}
}
var student = new Student('若川');
console.log(student); // {name: '若川'}
Видно, что: здесьStudent
в функцииthis
направлениеnew Student()
сгенерированный объектstudent
.
Резюме 2: Из этого примераnew
Оператор делает еще одну вещь:
- Результирующий новый объект привязывается к вызову функции
this
.
Далее продолжаем смотреть на обновленную версиюПример 3:
// 例子3
function Student(name){
this.name = name;
// this.doSth();
}
Student.prototype.doSth = function() {
console.log(this.name);
};
var student1 = new Student('若');
var student2 = new Student('川');
console.log(student1, student1.doSth()); // {name: '若'} '若'
console.log(student2, student2.doSth()); // {name: '川'} '川'
student1.__proto__ === Student.prototype; // true
student2.__proto__ === Student.prototype; // true
// __proto__ 是浏览器实现的查看原型方案。
// 用ES5 则是:
Object.getPrototypeOf(student1) === Student.prototype; // true
Object.getPrototypeOf(student2) === Student.prototype; // true
Что касается отношений прототипа JS, я видел эту картинку раньше, и я подумал, что это очень хорошо, я поделюсь ею с вами.
Резюме 3: Этот пример 3 еще раз доказываетРезюме 1серединапункт 2. То есть объект будет выполнен[[Prototype]]
(это,__proto__
)Ссылка на сайт. и черезnew Student()
Каждый созданный объект в конечном итоге будет[[Prototype]]
ссылка на этоStudent.protytype
на объекте.
Внимательные студенты могут обнаружить, что функции в этих трех примерах не возвращают значения. Итак, что произойдет, если есть возвращаемое значение. Тогда смотрите дальшеПример 4
// 例子4
function Student(name){
this.name = name;
// Null(空) null
// Undefined(未定义) undefined
// Number(数字) 1
// String(字符串)'1'
// Boolean(布尔) true
// Symbol(符号)(第六版新增) symbol
// Object(对象) {}
// Function(函数) function(){}
// Array(数组) []
// Date(日期) new Date()
// RegExp(正则表达式)/a/
// Error (错误) new Error()
// return /a/;
}
var student = new Student('若川');
console.log(student); {name: '若川'}
После того, как автор протестировал эти семь типовТипы JavaScript MDN, результат: первые шесть основных типов возвращаются нормально{name: '若川'}
,НазадObject
(ВключаютFunctoin
, Array
, Date
, RegExg
, Error
) вернет эти значения напрямую.
Это приводит к выводу 4:
- Если функция не возвращает тип объекта
Object
(ВключаютFunctoin
,Array
,Date
,RegExg
,Error
),Такnew
Вызовы функций в выражениях автоматически возвращают этот новый объект.
Объединение этих резюме вместе:
- Создается новый объект.
- Этот объект будет выполнен
[[Prototype]]
(это,__proto__
)Ссылка на сайт. - Результирующий новый объект привязывается к вызову функции
this
. - пройти через
new
Каждый созданный объект в конечном итоге будет[[Prototype]]
ссылка на эту функциюprototype
на объекте. - Если функция не возвращает тип объекта
Object
(ВключаютFunctoin
,Array
,Date
,RegExg
,Error
),Такnew
Вызовы функций в выражениях автоматически возвращают этот новый объект.
новая фиктивная реализация
Зная эти явления, мы можем смоделироватьnew
оператор. Почтовый код и комментарии напрямую
/**
* 模拟实现 new 操作符
* @param {Function} ctor [构造函数]
* @return {Object|Function|Regex|Date|Error} [返回结果]
*/
function newOperator(ctor){
if(typeof ctor !== 'function'){
throw 'newOperator function the first param must be a function';
}
// ES6 new.target 是指向构造函数
newOperator.target = ctor;
// 1.创建一个全新的对象,
// 2.并且执行[[Prototype]]链接
// 4.通过`new`创建的每个对象将最终被`[[Prototype]]`链接到这个函数的`prototype`对象上。
var newObj = Object.create(ctor.prototype);
// ES5 arguments转成数组 当然也可以用ES6 [...arguments], Aarry.from(arguments);
// 除去ctor构造函数的其余参数
var argsArr = [].slice.call(arguments, 1);
// 3.生成的新对象会绑定到函数调用的`this`。
// 获取到ctor函数返回结果
var ctorReturnResult = ctor.apply(newObj, argsArr);
// 小结4 中这些类型中合并起来只有Object和Function两种类型 typeof null 也是'object'所以要不等于null,排除null
var isObject = typeof ctorReturnResult === 'object' && ctorReturnResult !== null;
var isFunction = typeof ctorReturnResult === 'function';
if(isObject || isFunction){
return ctorReturnResult;
}
// 5.如果函数没有返回对象类型`Object`(包含`Functoin`, `Array`, `Date`, `RegExg`, `Error`),那么`new`表达式中的函数调用会自动返回这个新的对象。
return newObj;
}
Наконец-то реализовано с помощью моделированияnewOperator
функция проверки предыдущегоПример 3:
// 例子3 多加一个参数
function Student(name, age){
this.name = name;
this.age = age;
// this.doSth();
// return Error();
}
Student.prototype.doSth = function() {
console.log(this.name);
};
var student1 = newOperator(Student, '若', 18);
var student2 = newOperator(Student, '川', 18);
// var student1 = new Student('若');
// var student2 = new Student('川');
console.log(student1, student1.doSth()); // {name: '若'} '若'
console.log(student2, student2.doSth()); // {name: '川'} '川'
student1.__proto__ === Student.prototype; // true
student2.__proto__ === Student.prototype; // true
// __proto__ 是浏览器实现的查看原型方案。
// 用ES5 则是:
Object.getPrototypeOf(student1) === Student.prototype; // true
Object.getPrototypeOf(student2) === Student.prototype; // true
видно что подходитnew
оператор. Читатели могут указать, что не так или что можно улучшить.
Просмотрите эту симуляциюnew
функцияnewOperator
Реализация, самый большой вклад должен принадлежатьObject.create()
этоES5
который предоставилAPI
.
Пример использования Object.create()
Я также упомянул об этом в статье, которую я составил ранее, вы можете прочитать ееВесь API-анализ объектов JavaScript
Object.create(proto, [propertiesObject])
метод создает новый объект, используя существующий объект для предоставления __proto__ вновь созданного объекта.
Он принимает два параметра, но вторым необязательным параметром является дескриптор атрибута (обычно не используется, по умолчаниюundefined
).
var anotherObject = {
name: '若川'
};
var myObject = Object.create(anotherObject, {
age: {
value:18,
},
});
// 获得它的原型
Object.getPrototypeOf(anotherObject) === Object.prototype; // true 说明anotherObject的原型是Object.prototype
Object.getPrototypeOf(myObject); // {name: "若川"} // 说明myObject的原型是{name: "若川"}
myObject.hasOwnProperty('name'); // false; 说明name是原型上的。
myObject.hasOwnProperty('age'); // true 说明age是自身的
myObject.name; // '若川'
myObject.age; // 18;
для не поддерживаемыхES5
браузер,MDN
предоставляется наployfill
план.
if (typeof Object.create !== "function") {
Object.create = function (proto, propertiesObject) {
if (typeof proto !== 'object' && typeof proto !== 'function') {
throw new TypeError('Object prototype may only be an Object: ' + proto);
} else if (proto === null) {
throw new Error("This browser's implementation of Object.create is a shim and doesn't support 'null' as the first argument.");
}
if (typeof propertiesObject != 'undefined') throw new Error("This browser's implementation of Object.create is a shim and doesn't support a second argument.");
function F() {}
F.prototype = proto;
return new F();
};
}
На этом статья в основном закончена. Спасибо читателям, что увидели это.
Наконец, чтобы подвести итог:
-
new
Что вы наделали:
- Создается новый объект.
- Этот объект будет выполнен
[[Prototype]]
(это,__proto__
)Ссылка на сайт.- Результирующий новый объект привязывается к вызову функции
this
.- пройти через
new
Каждый созданный объект в конечном итоге будет[[Prototype]]
ссылка на эту функциюprototype
на объекте.- Если функция не возвращает тип объекта
Object
(ВключаютFunctoin
,Array
,Date
,RegExg
,Error
),Такnew
Вызовы функций в выражениях автоматически возвращают этот новый объект.
- как имитировать
// 去除了注释
function newOperator(ctor){
if(typeof ctor !== 'function'){
throw 'newOperator function the first param must be a function';
}
newOperator.target = ctor;
var newObj = Object.create(ctor.prototype);
var argsArr = [].slice.call(arguments, 1);
var ctorReturnResult = ctor.apply(newObj, argsArr);
var isObject = typeof ctorReturnResult === 'object' && ctorReturnResult !== null;
var isFunction = typeof ctorReturnResult === 'function';
if(isObject || isFunction){
return ctorReturnResult;
}
return newObj;
}
Читатели могут указать, что не так или что можно улучшить. Кроме того, если вы считаете, что текст хороший, вы можете поставить лайк, что также является своеобразной поддержкой автора.
Избранные статьи автора
Изучите общую архитектуру исходного кода sentry и создайте собственный SDK для мониторинга исключений переднего плана.
Изучите общую архитектуру исходного кода lodash и создайте собственную библиотеку классов функционального программирования.
Изучите общую архитектуру исходного кода подчеркивания и создайте собственную библиотеку классов функционального программирования.
Изучите общую архитектуру исходного кода jQuery и создайте собственную библиотеку js.
Интервьюер спросил: наследование JS
Интервьюер спросил: этот пункт JS
Интервьюер спросил: Могу ли я смоделировать вызов и применить методы JS?
Интервьюер спросил: Могу ли я смоделировать метод привязки, реализующий JS?
Интервьюер спросил: Могу ли я смоделировать новый оператор, реализующий JS?
Внешний интерфейс использует сканер puppeteer для создания PDF-файла «React.js Book» и его слияния.
о
Автор: Чанг ИВакагаваНазвание смешано в реках и озерах. По дороге на фронт | Энтузиасты РРТ | Знаю очень мало, только хорошо учусь.
личный блог
segmentfault
Передняя колонка обзора, открылПередний планКолонка, добро пожаловать на внимание~
Колонка самородков, добро пожаловать, обратите внимание~
Знайте переднюю колонку видения, открылПередний планКолонка, добро пожаловать на внимание~
github blog, спроситьstar
^_^~
Публичный аккаунт WeChat Ruochuan Vision
[Видение Вакагава] Публичный аккаунт Wechat, который может быть интересным, прошу обратить внимание. Вы также можете добавить WeChatruochuan12
, укажите источник и втяните вас в [Front-end Vision Exchange Group].