Сводка по устранению неполадок, связанных с тем, что вы не знаете, JS

внешний интерфейс JavaScript

Недавно я прочитал два буклета You-Dont-Know-JS.В процессе чтения книги, чтобы облегчить будущую индексацию и более глубокое понимание, а также чтобы не забыть, я сделал в каждом буклете несколько более сложных пунктов. отредактировано следующим образом.

Адрес этой статьи:блог.Hunan-E. Speciality/post/ is-shop…

types & grammer

  1. Судить о следующих результатах

    var s = 'abc';
    s[1] = 'B';
    
    console.log(s);
    
    var l = new String('abc');
    l[1] = 'B';
    console.log(l);
    

    stringи его объект-оболочка (Boxed Object) является неизменяемым (неизменяемым) типом, поэтому его нельзя изменить (изменить на месте), поэтомуStringВсе методы возвращают новую строку без изменения самой себя.

  2. Как изменить порядок строки?

    s.split('').reverse().join('')

  3. Подключите, почему вы не можете использовать его напрямуюArray.prototype.reverse.call(s)Строка в обратном порядке?

    Когда массив перевернутl.reverse()изменит l сам. Как и в первом вопросе,stringне может изменить себя.

  4. Судя по следующим результатам, почему так происходит, и как провести корректное сравнение?

    0.1 + 0.2 === 0.3;
    0.8 - 0.6 === 0.2;
    

    Числа с плавающей запятой хранят 64-битную двойную точность в соответствии со стандартом IEEE 754, которая может представлять 2 ^ 64 числа, а числа с плавающей запятой бесконечны, что означает, что некоторые числа с плавающей запятой должны иметь потерю точности. Введите маленькое значение при сравненииNumber.EPSILONошибка допуска, ее значение равно2^-52.

    function equal (a, b) {
      return Math.abs(a - b) < Number.EPSILON
    }
    
  5. Как оценить значение как целое число?

    // ES6
    Number.isInteger(num);
    
    // ES5
    if (!Number.isInteger) {
      Number.isInteger = function(num) {
        return typeof num == "number" && num % 1 == 0;
      };
    }
    
  6. Как определить, что значение равно +0?

    function isPosZero (n) {
      return n === 0 && 1 / n === Infinity
    }
    
  7. 'abc'.toUpperCase()В «abc» как примитивное значение, как получить доступtoUpperCaseметод

    когдаprimitive valueПри доступе к свойству или методу он автоматически преобразуется в объект-оболочку. В качестве альтернативы вы можете использоватьObject.prototype.valueOf()Распаковка.

  8. Оцените следующие результаты (обертки Boxing)

    function foo() {
      console.log(this)
    }
    
    foo.call(3);
    

    Номер(3). Причина описана выше.

  9. Оцените следующие результаты

    Array.isArray(Array.prototype)
    

    истинный Прототипы встроенных объектов не являются чистыми объектами, такими какDate.prototypeдата,Set.prototypeустановлен.

  10. Оцените следующие результаты

    Boolean(new Boolean(false));
    Boolean(document.all);
    
    [] == '';
    [3] == 3;
    [] == false;
    42 == true;
    

    Новый Boolean () Возвращает объект, правда Документ. Все, исторические вопросы, ссылказдесьЛожное значение относится к значению, которое будет принудительно равно ложному, и есть следующие пять. Все остальное, кроме этого, будет преобразовано в true

    • undefined
    • null
    • false
    • +0, -0, and NaN
    • ""

    You-Dont-Know-JS#user-content-toboolean

  11. Определите следующие проблемы с кодом (TDZ)

    var a = 3;
    let a;
    

    Это проблема временной мертвой зоны, A нельзя использовать до объявления let a.

  12. Определите следующие проблемы с кодом (TDZ)

    var x = 3;
    
    function foo (x=x) {
        // ..
    }
    
    foo()
    

    Аналогично, в параметрах функции по умолчанию также есть TDZ.

scope & closures

  1. var a = 2середина,Engine,Scope,Compilerкакую работу проделал

  2. Оцените следующие результаты (лексический объем)

    var scope = 'global scope';
    function checkScope () {
      var scope = 'local scope';
      function f() {
        return scope; 
      }
      return f;
    }
    
    checkScope()();
    

    'local scope'

    Поскольку js является лексической областью видимости, при доступе к переменной она сначала будет искать в текущей области видимости, а если ее не удастся найти, она будет искать во вложенной области видимости, пока не будет найдена. Если не нашли, сообщитеReferenceError.

  3. Оценка следующих результатов (Подъем)

    console.log(a);
    var a = 3;
    

    undefined

    Приведенный выше код будет интерпретирован компилятором как

    var a;
    console.log(a);
    a = 3;
    
  4. Оцените следующие результаты (функция прежде всего)

    var foo = 1;
    function foo () {
    
    }
    console.log(foo);
    

    1. Функции также поднимаются, поэтому они переопределяются присваиваниями.

  5. Оцените следующие результаты (IIFE & Function First)

    var foo = 1;
    (function () {
      foo = 2;
      function foo () {}
    
      console.log(foo);
    })()
    
    console.log(foo);
    

    2, 1

    Приведенный выше код будет интерпретирован компилятором как следующая форма

    var foo = 1;
    (function () {
      var foo;
      function foo () {
      }
    
      foo = 2;
      console.log(foo);
    })()
    
    console.log(foo);
    
  6. Судя по следующим результатам, как вывести по порядку (Замыкание)

    for (var i = 0; i < 10; i++) {
      setTimeout(function () {
        console.log(i);
      }, 1000)
    }
    

    Примерно через 1 с непрерывно выводятся 10 10 с. Поскольку область действия на уровне блоков отсутствует, вы можете изменить var на let или обернуть setTimeout с помощью IIFE.

this & object prototypes

Примечание. Следующие элементы находятся в среде браузера.

  1. Оценка следующих результатов (привязка по умолчанию)

    function foo() {
      "use strict";
      console.log( this.a );
    }
    
    var a = 2;
    
    foo();
    

    Будет сообщено об ошибке.В строгом режиме функции this в привязке по умолчанию указывает на undefined.

  2. Оцените следующие результаты

    "use strict";
    var a = 2;
    let b = 3;
    
    console.log(this.a, this.b);
    

    2, undefined

    В среде браузера это указывает на окно, и переменные, объявленные var, будут связаны с окном. Переменные, объявленные с помощью let, не будут зависать в окне.

  3. Оцените следующие результаты (строгий режим и привязка по умолчанию)

    function foo() {
      console.log( this.a );
    }
    
    var a = 2;
    
    (function(){
      "use strict";
    
      foo();
    })();
    

    2

    Строгий режим устанавливается только в функциях, которые имеют это, и это не определено. Так что нормально будет выводить.

  4. Оценка следующих результатов (жесткая привязка)

    function foo () {
      console.log(this.a);
    }
    
    const o1 = { a: 3 };
    const o2 = { a: 4 };
    
    foo.bind(o1).bind(o2)();
    

    3

    bind является жестким связыванием, и его нельзя связать снова после первого связывания.

  5. Как добитьсяFunction.prototype.bindа такжеFunction.prototype.softBind

    bind является жестким связыванием, softBind может связывать его несколько раз. Примерный код реализации выглядит следующим образом. Второй параметр bind может задавать параметры функции, поэтому bind также является частичной функцией. Кроме того, привязку также необходимо учитыватьnewСлучай.Но следующие примеры в основном сосредоточены на разнице между жестким и мягким связыванием.

    Function.prototype.fakeBind = function (obj) {
      var self = this;
      return function () {
        self.call(obj);
      }
    }
    
    Function.prototype.softBind = function(obj) {
      var self = this;
      return function () {
        self.call(this === window? obj : this);
      }
    };
    
  6. newО том, что получилось в процессе, судите по следующим результатам (новинка)

    function F () {
      this.a = 3;
      return {
        a: 4;
      }
    }
    
    const f = new F();
    console.log(f.a);
    

    4

    newПроцесс примерно такой

    1. создать новый объект
    2. это указывает на экземпляр и выполняет функцию
    3. Если не возвращается явно, этот экземпляр возвращается по умолчанию

    Поскольку функция явно возвращает объект в конце, она печатает 4

  7. чтоdata descriptorа такжеaccessor descriptor

    оба проходятObject.defineProperty()Определение, есть два открытых ключа

    • настраиваемый устанавливает, можно ли удалить ключ
    • enumerable устанавливает, может ли он быть пройден

    Дескриптор данных имеет следующие ключевые значения

    • доступен для записи, можно ли изменить ключ
    • value

    Дескриптор доступа имеет следующие ключи

    • set
    • получать В качестве альтернативы дескрипторы доступа также могут быть представлены как литералы.
    const obj = {
      get a() {},
      set a(val) {}
    }
    

    вьюcomputedВнутренний принцип заключается в том, чтоget,а такжеwatchВнутренний принципset

  8. Как получить доступ к свойствам объекта? ([[Получать]])

    Доступ к свойствам объекта запускает операцию [[Get]], которая примерно описывается следующим образом.

    1. Перехвачен ли прокси, если перехвачен, проверьте возвращаемое значение перехватчика, если не перехвачен, перейдите к следующему шагу
    2. Проверьте его собственные свойства, если он не найден, перейдите к следующему шагу.
    3. Если не найдено, найдите цепочку прототипов, если не найдено, верните неопределенное значение.

    Процесс поиска очень похож на переменную поиска Scope, за исключением того, что если свойство объекта не найдено, возвращается неопределенное значение, а переменная не найдена и сообщается об ошибке ссылки.

  9. Как присвоить значение свойству объекта ([[Put]])

    Присвоение свойства объекту запускает операцию [[Put]], которая примерно описывается следующим образом.

    1. Проверьте, не перехвачен ли прокси
    2. Если свойство объекта является собственным свойством (obj.hasOwnProperty('a') === true)
      1. Если свойство является дескриптором доступа, вызовите функцию установки
      2. Если свойство является дескриптором данных, проверьте, доступно ли для записи
      3. Обычные свойства, прямое назначение
    3. если свойство объекта существует в цепочке прототипов
      1. Если свойство является дескриптором доступа, вызовите функцию установки
      2. Если свойство является дескриптором данных, проверьте, доступно ли для записи. Если он доступен для записи, он будет переопределен собственными свойствами, в противном случае в строгом режиме будет сообщено об ошибке.
      3. Обычные свойства, переопределяемые собственными свойствами
    4. Если объект не существует в цепочке прототипов, напрямую присвойте значение его собственному свойству.
  10. Как перебирать объект (?iterator)

    Задайте свойство Symbol.iterator для объекта.

  11. Как реализовать наследование (Object.create и вызов)

    В эпоху ES6 наследование может быть достигнуто просто через class & extends, а в эпоху ES5 используются следующие методы.

    function A () {}
    
    function B () {
      A.call(this)
    }
    
    B.prototype = Object.create(A.prototype)
    // B.prototype = new A()     不推荐
    
  12. Как добитьсяObject.create

    Что касается того, почему это не рекомендуется при наследованииnew, причина в том, что вам сложно гарантировать, что A является чистой функцией, например, она будет иметь свои свойства, может манипулировать DOM и т.д. Ниже приведена простая версия реализации без второго параметра.

    Object.create = function (o) {
      function F() {}
      F.prototype = o;
      return new F();
    }
    

Обратите внимание на публичный аккаунтГорная Луна Путешествие, зафиксируйте мой технический рост, добро пожаловать в общение

欢迎关注公众号山月行,记录我的技术成长,欢迎交流