Быстро освоить основы JavaScript-интервью (2)

JavaScript

Переводчик пресса:Суммируйте большое количество базовых знаний 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()函数不一样。 использоватьbind

    function 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' }
    
  • this

    var 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/