предисловие
Здравствуйте, яВакагава. Это четвертая статья из серии «Вопросы интервьюера», призванная помочь читателям улучшить
JS
базовые знания, в том числеnew、call、apply、this、继承
связанная информация.
面试官问系列
Статья выглядит следующим образом: Заинтересованные читатели могут нажать, чтобы прочитать.
1.Интервьюер спросил: Могу ли я смоделировать новый оператор, реализующий JS?
2.Интервьюер спросил: Могу ли я смоделировать метод привязки, реализующий JS?
3.Интервьюер спросил: Могу ли я смоделировать вызов и применить методы JS?
4.Интервьюер спросил: этот пункт JS
5.Интервьюер спросил: наследование JS
Интервьюер задает много тестовых вопросов, и они в основном меняют способ расследования.this
Укажите, см. пару кандидатовJS
Прочны ли базовые знания.
Читатели могут сначала потянуть вниз, чтобы прочитать резюме, а затем в Google (или на различных технологических платформах) выполнить поиск нескольких похожих статей, чтобы увидеть, чем статьи, написанные автором, отличаются от других (вы можете прокомментировать различия в поле для комментариев).
Прилагается к абзацу предыдущей письменной статьи: уже много
this
Почему ты снова должен писать это сам? Обучение похоже на большую гору: люди взбираются на гору по разным дорогам и делятся пейзажами, которые видят. Возможно, вы не сможете увидеть пейзаж, который видят другие, и почувствовать настроение других. Только когда вы отправляетесь в горы самостоятельно, вы можете увидеть разные пейзажи и испытать более глубокие переживания.
функциональныйthis
Связывание во время вызова полностью зависит от того, где вызывается функция (то есть, как вызывается функция). выяснитьthis
На что указывает указатель, вы должны знать, как вызывается соответствующая функция.
глобальный контекст
Как в обычном, так и в строгом режиме это указывает на объект верхнего уровня (в браузере этоwindow
).
this === window // true
'use strict'
this === window;
this.name = '若川';
console.log(this.name); // 若川
контекст функции
Обычный шаблон вызова функции
// 非严格模式
var name = 'window';
var doSth = function(){
console.log(this.name);
}
doSth(); // 'window'
ты можешь ошибатьсяwindow.doSth()
называется, поэтому он указывает наwindow
. Хотя в этом примереwindow.doSth
равноdoSth
.name
равныйwindow.name
. В приведенном выше коде это потому, чтоES5
, глобальные переменные монтируются на объекты верхнего уровня (браузерwindow
)середина.
На самом деле это не так.
// 非严格模式
let name2 = 'window2';
let doSth2 = function(){
console.log(this === window);
console.log(this.name2);
}
doSth2() // true, undefined
В этом примереlet
Никакие свойства не добавляются к объекту верхнего уровня (браузер является окном),window.name2和window.doSth
обеundefined
.
В строгом режиме, в нормальных функцияхthis
вести себя по-разному, какundefined
.
// 严格模式
'use strict'
var name = 'window';
var doSth = function(){
console.log(typeof this === 'undefined');
console.log(this.name);
}
doSth(); // true,// 报错,因为this是undefined
Посмотрел "Ты не знаешь"JavaScript
«Читатели предыдущего тома должны знать, что в книге это называется связыванием по умолчанию.
правильноcall
,apply
Знакомые читатели проведут аналогию:
doSth.call(undefined);
doSth.apply(undefined);
Эффект тот же,call
,apply
Одной из функций является изменение функции вthis
указывает на первый параметр.
Первый параметрundefined
илиnull
, в нестрогом режиме относится кwindow
. В строгом режиме это относится к первому параметру. Это объяснено подробно позже.
Часто встречается такой код (функция обратного вызова), который на самом деле является обычным режимом вызова функции.
var name = '若川';
setTimeout(function(){
console.log(this.name);
}, 0);
// 语法
setTimeout(fn | code, 0, arg1, arg2, ...)
// 也可以是一串代码。也可以传递其他函数
// 类比 setTimeout函数内部调用fn或者执行代码`code`。
fn.call(undefined, arg1, arg2, ...);
Паттерн вызова функции (метода) в объекте
var name = 'window';
var doSth = function(){
console.log(this.name);
}
var student = {
name: '若川',
doSth: doSth,
other: {
name: 'other',
doSth: doSth,
}
}
student.doSth(); // '若川'
student.other.doSth(); // 'other'
// 用call类比则为:
student.doSth.call(student);
// 用call类比则为:
student.other.doSth.call(student.other);
Но часто встречаются следующие сценарии, когда функция в объекте присваивается переменной. На самом деле это снова становится нормальной функцией, поэтому используются правила для обычных функций (привязка по умолчанию).
var studentDoSth = student.doSth;
studentDoSth(); // 'window'
// 用call类比则为:
studentDoSth.call(undefined);
call、apply、bind
режим вызова
упомянутый вышеcall
,apply
, читайте здесь подробно. пройти первымMDN
узнатьcall
а такжеapply
Документация MDN: Function.prototype.call()
грамматика
fun.call(thisArg, arg1, arg2, ...)
thisArg
существуетfun
указывается при выполнении функцииthis
стоимость. Следует отметить, что указанныйthis
Значение не обязательно верно, что функция фактически выполняется.this
значение, если эта функция находится внестрогий режимниже он указан какnull
а такжеundefined
изthis
Значение будет автоматически указывать на глобальный объект (в браузере этоwindow
Объект), значение является исходным значением (число, строка, логическое значение)this
Укажет на объект с автоматической оболочкой для этого примитивного значения.
arg1, arg2, ...
указанный список параметров
возвращаемое значение
Возвращаемое значение — это возвращаемое значение метода, который вы вызвали. Если у метода нет возвращаемого значения, вернитеundefined
.
apply
а такжеcall
аналогичный. Только параметры разные. Его аргумент представляет собой массив (или подобный массиву).
По параметрамthisArg
описание, можно узнать, что,call
это изменить функциюthis
указывает наthisArg
, и выполнить функцию, которая также делаетJS
Много гибкости. В строгом режиме,thisArg
Примитивное значение — это тип значения, то есть примитивное значение. не будет обернут в объект. Например:
var doSth = function(name){
console.log(this);
console.log(name);
}
doSth.call(2, '若川'); // Number{2}, '若川'
var doSth2 = function(name){
'use strict';
console.log(this);
console.log(name);
}
doSth2.call(2, '若川'); // 2, '若川'
Хотя в целом неthisArg
Параметры записываются как типы значений. Но все же нужно знать эти знания.
Я уже писал статью:Интервьюер спросил: Можно ли это смоделировать?JS
изcall
а такжеapply
методЭто использовать функцию на объектеthis
Укажите на этот объект, чтобы имитировать реализациюcall
а такжеapply
из. Заинтересованные читатели думают, как это реализовать, а потом идут смотреть авторскую реализацию.
bind
а такжеcall
а такжеapply
Аналогично изменяется и первый параметрthis
Укажите на, но возвращаемое значение — это новая функция, и новую функцию также можно использовать в качестве конструктора (new
)передача.MDN Function.prototype.bind
bind()
метод создает новую функцию, когда эта новая функция вызываетсяthis
Значение ключа — это значение, которое он предоставляет, а первые несколько элементов в его списке параметров — это последовательность параметров, указанная при создании.
грамматика:
fun.bind(thisArg[, arg1[, arg2[, ...]]])
параметр:
thisArgЗначение, передаваемое целевой функции в качестве параметра this при вызове связанной функции. При использованииnew
оператор строит связанную функцию, значение игнорируется. когда используешьbind
существуетsetTimeout
При создании функции (предоставленной как обратный вызов) вthisArg
Любое переданное примитивное значение будет преобразовано вobject
. Если связанные параметры не указаны,this
рассматривается как новая функцияthisArg
.arg1, arg2, ...Когда связанная функция вызывается, эти параметры передаются связанному методу перед фактическими аргументами.возвращаемое значениеВозврат из указанногоthis
Копия исходной функции, преобразованная по значению и параметрам инициализации.
Я уже писал статью:Интервьюер спросил: Можно ли это смоделировать?JS
изbind
методИспользоватьcall
а такжеapply
указать на этоthisArg
параметры, чтобы имитировать реализациюbind
из. Заинтересованные читатели думают, как это реализовать, а потом идут смотреть авторскую реализацию.
Шаблон вызова конструктора
function Student(name){
this.name = name;
console.log(this); // {name: '若川'}
// 相当于返回了
// return this;
}
var result = new Student('若川');
использоватьnew
Оператор вызывает функцию, которая автоматически выполняет следующие действия.
- Создается новый объект.
- Этот объект будет выполнен
[[Prototype]]
(то есть,__proto__
)Связь.- Результирующий новый объект привязывается к вызову функции
this
.- пройти через
new
Каждый созданный объект в конечном итоге будет[[Prototype]]
ссылка на эту функциюprototype
на объекте.- Если функция не возвращает тип объекта
Object
(ВключатьFunctoin
,Array
,Date
,RegExg
,Error
),Такnew
Вызовы функций в выражениях автоматически возвращают этот новый объект.
Отсюда вы можете узнать:new
При вызове оператораthis
Указывает на результирующий новый объект.Специальное напоминание,new
Возвращаемое значение вызова, если объект или функция не возвращаются явно, возвращается новый сгенерированный объект..
function Student(name){
this.name = name;
// return function f(){};
// return {};
}
var result = new Student('若川');
console.log(result); {name: '若川'}
// 如果返回函数f,则result是函数f,如果是对象{},则result是对象{}
Многие люди или статьи игнорируют этот момент и используют его прямо и просто.typeof
Объект суда. Хотя возврат не будет показан при фактическом использовании, интервьюер спросит.
Я написал статью раньшеИнтервьюер спросил: Можно ли это смоделировать?JS
изnew
оператор, заключается в использовании apply, чтобы указать this на сгенерированный вновь сгенерированный объект. Заинтересованные читатели думают, как это реализовать, а потом идут смотреть авторскую реализацию.
Вызов шаблонов в цепочке прототипов
function Student(name){
this.name = name;
}
var s1 = new Student('若川');
Student.prototype.doSth = function(){
console.log(this.name);
}
s1.doSth(); // '若川'
Найдет это знакомым. Это шаблон вызова метода для объекта. Естественно, он указывает на сгенерированный новый объект.
Если объект наследуется от других объектов. Он также просматривает цепочку прототипов.
Используйте приведенный выше кодES6
серединаclass
Правило написания таково:
class Student{
constructor(name){
this.name = name;
}
doSth(){
console.log(this.name);
}
}
let s1 = new Student('若川');
s1.doSth();
babel
es6
Перевести вes5
, ты можешь пойти вbabeljs网站转换测试
Попробуй сам.
'use strict';
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
var Student = function () {
function Student(name) {
_classCallCheck(this, Student);
this.name = name;
}
_createClass(Student, [{
key: 'doSth',
value: function doSth() {
console.log(this.name);
}
}]);
return Student;
}();
var s1 = new Student('若川');
s1.doSth();
Это показывает,ES6
изclass
Это также реализуется через симуляцию конструктора, которая является своего рода синтаксическим сахаром.
Шаблон вызова функции стрелки
Давайте сначала рассмотрим важные различия между стрелочными функциями и обычными функциями:
1. не собственный
this
,super
,arguments
а такжеnew.target
связывать.
2. Не может быть использованnew
звонить.
3. Нет объекта-прототипа.
4, не может быть измененthis
привязка.
5. Формальное имя параметра не может повторяться.
Стрелочные функции не имеютthis
Binding, значение которого необходимо определить, просматривая цепочку областей видимости.
Если стрелочная функция содержится в нестрелочной функции, тоthis
Привязка — ближайший слой нестрелочных функцийthis
,иначеthis
В качестве значения устанавливается глобальный объект.
Например:
var name = 'window';
var student = {
name: '若川',
doSth: function(){
// var self = this;
var arrowDoSth = () => {
// console.log(self.name);
console.log(this.name);
}
arrowDoSth();
},
arrowDoSth2: () => {
console.log(this.name);
}
}
student.doSth(); // '若川'
student.arrowDoSth2(); // 'window'
Фактически эквивалентно функции вне стрелокthis
это кэшированная обычная функция верхнего уровня стрелочной функцииthis
. Если нормальной функции нет, то это глобальный объект (в браузере этоwindow
).
То есть пройти невозможноcall
,apply
,bind
связать функцию стрелкиthis
(это не само по себеthis
). а такжеcall
,apply
,bind
Можно привязать обычную функцию верхнего слоя стрелочной функции кэшаthis
.
Например:
var student = {
name: '若川',
doSth: function(){
console.log(this.name);
return () => {
console.log('arrowFn:', this.name);
}
}
}
var person = {
name: 'person',
}
student.doSth().call(person); // '若川' 'arrowFn:' '若川'
student.doSth.call(person)(); // 'person' 'arrowFn:' 'person'
DOM
вызов обработчика событий
addEventerListener, attachEvent, по клику
<button class="button">onclick</button>
<ul class="list">
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
<script>
var button = document.querySelector('button');
button.onclick = function(ev){
console.log(this);
console.log(this === ev.currentTarget); // true
}
var list = document.querySelector('.list');
list.addEventListener('click', function(ev){
console.log(this === list); // true
console.log(this === ev.currentTarget); // true
console.log(this);
console.log(ev.target);
}, false);
</script>
onclick
а такжеaddEventerListener
— элемент, указывающий на связанное событие.
некоторые браузеры, напримерIE6~IE8
использовать подattachEvent
,this
указать даwindow
.
Кстати: интервьюер тоже частоev.currentTarget
а такжеev.target
разница.ev.currentTarget
это элемент, к которому привязано событие, иev.target
элемент, который в данный момент запускает событие. Вот, например, разницаul
а такжеli
.
но можно и нажатьul
, тогдаev.currentTarget
а такжеev.target
Равный.
Функция функции обработчика событий в Inline
<button class="btn1" onclick="console.log(this === document.querySelector('.btn1'))">点我呀</button>
<button onclick="console.log((function(){return this})());">再点我呀</button>
первыйbutton
сам так себеtrue
, второйwindow
. Это не имеет ничего общего со строгим режимом.
Конечно, сейчас мы его так не используем, но иногда это случайно так пишется, и это нужно понимать.
фактическиthis
Существует много сценариев использования, таких как объектobject
серединаgetter
,setter
изthis
,new Function()
,eval
.
Но если вы освоите вышеперечисленное и проанализируете остальные, вы, естественно, решитесь.
Чаще используются обычные вызовы функций, вызовы объектных функций,new
передача,call、apply、bind
вызов, вызов функции стрелки.
Так каковы их приоритеты?
приоритет
И функция стрелкиthis
является обычной функцией верхнего уровняthis
или глобальный объект (в браузерах этоwindow
), поэтому исключено, не считается приоритетом.
var name = 'window';
var person = {
name: 'person',
}
var doSth = function(){
console.log(this.name);
return function(){
console.log('return:', this.name);
}
}
var Student = {
name: '若川',
doSth: doSth,
}
// 普通函数调用
doSth(); // window
// 对象上的函数调用
Student.doSth(); // '若川'
// call、apply 调用
Student.doSth.call(person); // 'person'
new Student.doSth.call(person);
Вы только представьте, если бы это былоStudent.doSth.call(person)
Если выполнить сначала, тоnew
Выполнить функцию. Нет проблем.
Однако на самом деле этот код ошибочен.приоритет операторадаnew
Он ниже номера точки, поэтому выполняетсяnew (Student.doSth.call)(person)
а такжеFunction.prototype.call
, хотя функция (apply
,bind
Это также функция), как функции стрелки, не может использоватьnew
передача. Так что это неправильно.
Uncaught TypeError: Student.doSth.call is not a constructor
Это потому, что внутри функции есть два разных метода:[[Call]]
а также[[Constructor]]
.
При использовании обычного вызова функции[[Call]]
будет казнен. При вызове с конструктором[[Constructor]]
будет казнен.call
,apply
,bind
а внутри стрелочной функции нет[[Constructor]]
метод.
Из приведенного выше примера видно, что обычные вызовы функций имеют самый низкий приоритет, за ними следуют функции над объектами.call(apply、bind)
метод вызова иnew
Приоритет вызывающего метода сравнивается в «JavaScript, которого вы не знаете».bind
а такжеnew
quoted.mdn
изbind
изployfill
выполнить,new
Функция после привязки игнорируется при вызовеbind
Первый параметр привязки (mdn
На самом деле есть еще некоторые проблемы в реализации .Заинтересованные читатели могут прочитать мои предыдущие статьи:Интервьюер спросил: Можно ли это смоделировать?JS
изbind
метод), проиллюстрироватьnew
Вызов имеет наивысший приоритет.
Так что их приоритетnew
позвонить >call、apply、bind
Вызовы > Вызовы функций для объектов > Обычные вызовы функций.
Суммировать
Если вы хотите определить значение запущенной функцииthis
Для привязки нужно найти место прямого вызова этой функции. после нахождения
Следующие четыре правила могут быть применены для оценкиthis
объект привязки.
-
new
вызов: привязать к вновь созданному объекту, примечание: показатьreturn
Функция или объект, возвращаемое значение которого не является вновь созданным объектом, а явно возвращенной функцией или объектом.
-
call
илиapply
( илиbind
) вызов: в строгом режиме выполнить привязку к указанному первому параметру. В нестрогом режимеnull
а такжеundefined
, указывая на глобальный объект (в браузереwindow
), остальные значения указывают наnew Object()
Завернутый объект.
- Вызов функции для объекта: привязка к этому объекту.
- Обычный вызов функции: привязать в строгом режиме к
undefined
, в противном случае привязанный к глобальному объекту.
ES6
Стрелочные функции в : Четыре стандартных правила привязки выше не используются, но определяются в соответствии с текущей лексической областьюthis
В частности, стрелочная функция наследует внешнюю функцию, а привязка вызова this (независимо от того, к чему привязано this), если внешней функции нет, она привязывается к глобальному объекту (в браузере этоwindow
). На самом деле это иES6
в предыдущем кодеself = this
Механизм тот же.
DOM
Функция события: обычно указывает на связанное событиеDOM
элементы, но в некоторых случаях связаны с глобальным объектом (например,IE6~IE8
изattachEvent
).
Важно отметить, что некоторые вызовы могут непреднамеренно использовать обычные правила связывания функций. Если вы хотите "безопаснее" игнорироватьthis
галстук
Конечно, вы можете использовать такой объект, как ø = Object.create(null)
, чтобы защитить глобальный объект.
Осмотр интервьюераthis
точка для расследованияnew、call、apply、bind
, стрелочные функции и т. д. Это распространяется на область действия, замыкания, цепочки прототипов, наследование, строгий режим и многое другое. Вот почему интервьюеры так любят это.
Читатели могут указать, что не так или что можно улучшить. Кроме того, если вы считаете, что текст хороший, вы можете поставить лайк, что также является своеобразной поддержкой автора.
экзаменационные вопросы
this
Экзаменационные вопросы по указыванию часто сочетаются с некоторыми операторами для изучения. После прочтения этой статьи вы можете захотеть пройти тест на следующие два вопроса интервью.Little Canghai: вопрос на собеседовании по интерфейсу JS, который часто презирают
Из этих двух наборов вопросов заново поймите JS this, объем, закрытие и объект.
Расширенное чтение
JavaScript Rollup вы не знаете
Ю Ю: Углубленная интерпретация JavaScript из спецификации ECMAScript.
Эта волна может дать отпор: продвинутые основы интерфейса (5): всесторонняя интерпретация этого
Избранные статьи автора
Изучите общую архитектуру исходного кода 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].