Переводчик пресса:Суммируйте большое количество базовых знаний JavaScript, это полезно!
为了保证可读性,本文采用意译而非直译。 Кроме того, авторские права на эту статью принадлежат оригинальному автору, а перевод предназначен только для ознакомления.
согласно сС 2014 года результат JavaScript является самым популярным языками программирования. Конечно, также разумно, в конце концов, треть работа о разработке нужна некоторые знания JavaScript. Итак, если вы хотите стать разработчиком, вы должны изучить язык.
Основная цель этого блога — обобщить все распространенные в интервью концепции, чтобы вы могли быстро их понять. (Поскольку содержание этой статьи слишком длинное и легко читаемое, для перевода она будет разделена на три блога, это вторая часть. Для первой части нажмитеУзнайте основные основы для интервью JavaScript (A))
Закрытие
Закрытие определяется функцией, и функция - это среда, в которой композиция. Мы объясняем это на примере изображения.
function sayHi(name){
var message = `Hi ${name}!`;
function greeting() {
console.log(message)
}
return greeting
}
var sayHiToJon = sayHi('Jon');
console.log(sayHiToJon) // ƒ() { console.log(message) }
console.log(sayHiToJon()) // 'Hi Jon!'
Пожалуйста, поймите этоvar sayHiToJon = sayHi('Jon');Выполнение этой строки кода,sayHiвыполнение функции, сначалаmessageрассчитывается, затем определяетсяgreetingфункция, на которую ссылается функцияmessageпеременная; наконец, возвратgreetingфункция.
Если вы следуете языку C/Java, идеям,sayHiToJonэквивалентноgreetingфункции, то будет сообщено об ошибке: сообщение не определено. Но это не то же самое в JavaScript, вотsayHiToJonФункция равнаgreetingmessage. Итак, когда мы звонимsayHiToJonmessageРаспечатай.因此,这里的闭包就是greetingФункция и содержащиеmessageпеременная среда. (Примечание: для простоты понимания этот абзац не был переведен в соответствии с исходным текстом.)
Одним из преимуществ замыканий является то, чтоИзоляция данных.我们同样用一个例子来说明:
function SpringfieldSchool() {
let staff = ['Seymour Skinner', 'Edna Krabappel'];
return {
getStaff: function() { console.log(staff) },
addStaff: function(name) { staff.push(name) }
}
}
let elementary = SpringfieldSchool()
console.log(elementary) // { getStaff: ƒ, addStaff: ƒ }
console.log(staff) // ReferenceError: staff is not defined
/* Closure allows access to the staff variable */
elementary.getStaff() // ["Seymour Skinner", "Edna Krabappel"]
elementary.addStaff('Otto Mann')
elementary.getStaff() // ["Seymour Skinner", "Edna Krabappel", "Otto Mann"]
существуетelementaryКогда вы были созданы,SpringfieldSchoolвернулся. то естьstaffнельзя получить доступ извне. Единственный способ получить к нему доступ — через функцию закрытия внутриgetStaffа такжеaddStaff.
Давайте посмотрим на вопрос интервью: что не так с кодом ниже и как это исправить?
const arr = [10, 12, 15, 21];
for (var i = 0; i < arr.length; i++) {
setTimeout(function() {
console.log(`The value ${arr[i]} is at index: ${i}`);
}, (i+1) * 1000);
}
Выход вышеуказанного кода все одинаково: «Значение undefined - это индекс: 4». Потому что все тоsetTimeoutАнонимные функции, определенные во всех, ссылаются на одну и ту же внешнюю переменную.i. Когда анонимная функция выполняется,iЗначение равно 4.
Этот вопрос можно изменить наIIFE(Представленный позже) метод для решения путем создания отдельной внешней области для каждой анонимной функции.
const arr = [10, 12, 15, 21];
for (var i = 0; i < arr.length; i++) {
(function(j) {
setTimeout(function() {
console.log(`The value ${arr[j]} is at index: ${j}`);
}, j * 1000);
})(i)
}
Конечно, есть и другой способ, используяletОбъявитьi.
const arr = [10, 12, 15, 21];
for (let i = 0; i < arr.length; i++) {
setTimeout(function() {
console.log(`The value ${arr[i]} is at index: ${i}`);
}, (i) * 1000);
}
Выражение функции (немедленное выражение функции) (IIFE) немедленно позвонить
IIFE — это функциональное выражение, которое вызывается сразу после определения. Обычно используется изолированно, когда вы хотите создать новую область для объявления переменной.
Его формат:(function(){....})(). Передние скобы используются для указания компилятора, который является не только определением функции, но задние скобки используются для выполнения функции.
var result = [];
for (var i=0; i < 5; i++) {
result.push( function() { return i } );
}
console.log( result[1]() ); // 5
console.log( result[3]() ); // 5
result = [];
for (var i=0; i < 5; i++) {
(function () {
var j = i; // copy current value of i
result.push( function() { return j } );
})();
}
console.log( result[1]() ); // 1
console.log( result[3]() ); // 3
Используйте IIFE CAN:
Контекст
Мы часто путаем среду (Context) с областью действия (Scope), позвольте мне кратко объяснить:
-
Контекст: определяется тем, как вызывается функция, часто ссылаясь на
this. - Объем: Доступные переменные.
Функция Call: Call, Apply, Bind
Эти три метода связаны с this для того, чтобы функционировать, разница заключается в способе вызова.
-
.call()Функция будет выполнена немедленно, вам нужно передать параметры по порядку; -
.apply()Немедленно выполнит функцию, вам необходимо поставить все комбинации параметров, переданных на массив;
.call()а также.apply()почти то же самое.哪个传入参数方便,你就选择哪个。
const Snow = {surename: 'Snow'}
const char = {
surename: 'Stark',
knows: function(arg, name) {
console.log(`You know ${arg}, ${name} ${this.surename}`);
}
}
char.knows('something', 'Bran'); // You know something, Bran Stark
char.knows.call(Snow, 'nothing', 'Jon'); // You know nothing, Jon Snow
char.knows.apply(Snow, ['nothing', 'Jon']); // You know nothing, Jon Snow
call
ES6 позволяет использовать новые операторы для преобразования массива в последовательность.
char.knows.call(Snow, ...["nothing", "Jon"]); // You know nothing, Jon Snow
.bind()Это возвращает новую функцию и соответствующие параметры и среду. Если вы хотите вызвать функцию позже, рекомендуется использоватьbind..bind()Преимущество функции в том, что она записывает среду выполнения, что полезно для асинхронных вызовов и программирования, управляемого событиями.
.bind()Способ передачи параметров иcallтакой же.
const Snow = {surename: 'Snow'}
const char = {
surename: 'Stark',
knows: function(arg, name) {
console.log(`You know ${arg}, ${name} ${this.surename}`);}
}
const whoKnowsNothing = char.knows.bind(Snow, 'nothing');
whoKnowsNothing('Jon'); // You know nothing, Jon Snow
это ключевое слово
Чтобы понять JavaScriptthisКлючевое слово, которое указывает, в частности, кто, иногда довольно сложно.thisЗначение обычно определяется средой выполнения функции. Проще говоря, среда выполнения относится к тому, как вызывается функция.thisПодобно заполнителю, он указывает на объект, который вызывает соответствующий метод при вызове метода.
Суды перечислены ниже в порядкеthisУкажите на правило. Если первое совпадает, то второе проверять не надо.
-
newпривязать - при использованииnewКогда ключевое слово вызывает функцию,thisУказывает на вновь построенный объект.function Person(name, age) { this.name = name; this.age =age; console.log(this); } const Rachel = new Person('Rachel', 30); // { age: 30, name: 'Rachel' } -
Явная привязка - при использовании
callилиapplyКогда мы явно передаем параметр объекта, этот параметр будет привязан кthis. Уведомление:.bind()函数不一样。 использоватьbindfunction fn() { console.log(this); } var agent = {id: '007'}; fn.call(agent); // { id: '007' } fn.apply(agent); // { id: '007' } var boundFn = fn.bind(agent); boundFn(); // { id: '007' } -
thisvar building = { floors: 5, printThis: function() { console.log(this); } } building.printThis(); // { floors: 5, printThis: function() {…} } -
thisГлобальный объект (браузер — это объект окна). Когда функция не привязана к объекту и определена индивидуально, функция по умолчанию привязана к глобальному объекту.function printWindow() { console.log(this) } printWindow(); // window object
Примечание. В следующих случаяхinnerв функцииthisуказать на глобальное.
function Dinosaur(name) {
this.name = name;
var self = this;
inner();
function inner() {
alert(this); // window object — the function has overwritten the 'this' context
console.log(self); // {name: 'Dino'} — referencing the stored value from the outer context
}
}
var myDinosaur = new Dinosaur('Dino');
- Лексическое это - при использовании
=>определить функцию,thisУказывает на внешний слой, когда функция определенаthis. Примечания: Предположительно и определенная лексика (=>), назови этоLexical this.
function Cat(name) {
this.name = name;
console.log(this); // { name: 'Garfield' }
( () => console.log(this) )(); // { name: 'Garfield' }
}
var myCat = new Cat('Garfield');
Строгий режим
если вы использовали"use strict"директива, код JavaScript будет выполняться в строгом режиме. В строгом режиме существуют определенные правила лексического анализа и обработки ошибок. Здесь я перечисляю некоторые из его преимуществ:
- Облегчает отладку: теперь сообщается об ошибках, которые ранее игнорировались, например о присвоении значения недоступной для записи глобальной переменной или свойству;
- Избегайте случайного объявления глобальных переменных: присваивание неопределенной переменной сообщит об ошибке;
- Избегайте использования недействительной Удалить: попробуйте удалить переменную, функцию или свойство не может быть удалена, будет бросать ошибку;
- Избегайте повторяющихся имен свойств и значений параметров: повторяющиеся свойства и параметры функций в объекте вызовут ошибку (в ES6 это уже не так);
- сделать
eval()Более безопасно: вeval()Переменные и функции, определенные во внешней области, невидимы; - «Безопасное» преобразование для устранения этого в JavaScript: если
thisимеет значение null или не определено, не преобразуется в глобальный объект. То есть больше невозможно использовать this для ссылки на глобальный объект в браузере.
Для ошибок, которые не найдены в строгом режиме и на этапе тестирования, вы можете получить доступ к мониторингу онлайн в режиме реального времениFundebug.
Уведомление об авторских правах:
При перепечатании, укажите автора Fundebug и адрес этой статьи:
https://blog.fundebug.com/2018/01/22/the-definitive-javascript-handbook-for-a-developer-interview-2/