60 000 слов за пять дней, JavaScript-интервью

внешний интерфейс JavaScript
60 000 слов за пять дней, JavaScript-интервью

1. Что такое компилируемый язык? Что такое интерпретируемый язык?JSЧто это за язык?

1. Компилируемый язык

1. Объясните

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

2. Преимущества и недостатки

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

3. Примеры

C,C++Все компилируемые языки.

2. Интерпретируемый язык

1. Объясните

Программу не нужно компилировать, программа переводится на машинный язык при запуске и переводится каждый раз при выполнении.

2. Преимущества и недостатки

Интерпретируемые языки менее эффективны и не могут работать без интерпретатора, а вот их кроссплатформенные аналоги проще, достаточно предоставить конкретный интерпретатор.

3. Примеры

python,JSВсе интерпретируемые языки.

Во-вторых, обязательное преобразование типов и неявное преобразование типов.

1,JSКакие типы приведения и неявные преобразования типов существуют?

1. Принуждение

  • String()
  • Number()
  • Boolean()
  • parseInt()
  • parseFloat()

2. Неявное преобразование типов

  • + stringпреобразовать в число
  • a + " "преобразовать в строку
  • !varпреобразовать в логическое значение

类型转换

3. Основные типы данных и справочные типы данных

1. Разница

1. При использовании в качестве параметра функции:

  1. Базовые типы данных передаются в копии данных, и изменения в исходных данных не повлияют на входящие данные.
  2. Ссылочный тип данных передается в ссылочном адресе данных, и изменения в исходных данных повлияют на входящие данные.

2. Место хранения в памяти:

  1. Примитивные типы данных хранятся в стеке.
  2. Ссылочный тип данных хранит указатель в стеке, а объект данных, на который указывает указатель, хранится в куче.

2. Размещение стека и кучи в памяти

栈和堆在内存中的分配

eg:var a = {name: 'yuhua'}хранение переменных

  1. поместите этот код в代码区域 Code Segment;
  2. поместите переменнуюaположить в栈(Stack):本地变量、指针;
  3. Буду{name: 'yuhua'}положить вHeapTotal(堆):对象,闭包.

3.symbol

1. symbolКак получить его как ключевое имя объекта?

не могу получитьsymbolключ:

  1. for inа такжеfor ofПри обходе цикла не получитсяsymbolключ;
  2. Object.keys(),Object.getOwnPropertyNames(),JSON.stringify()метод недоступенsymbolключ;

может получитьsymbolключ:

  1. Object.getOwnPropertySymbols()Метод может получать и возвращать массив;
  2. Reflect.ownKeys()Может получить все имена ключей, включаяsymbolключ

2. symbolпреобразование типов

1) можно преобразовать вstring
const symbolKey = Symbol(123)
String(symbolKey) // "Symbol(123)"
symbolKey.toString() // "Symbol(123)"
2) Может быть преобразовано в логическое значение
Boolean(symbolKey) // true
3) Невозможно преобразовать в числа (ошибка)
Number(symbolKey)
Uncaught TypeError: Cannot convert a Symbol value to a number
    at Number (<anonymous>)
    at <anonymous>:1:1
4) Преобразовать в объект
b = Object(symbolKey)
Symbol {Symbol(123)}
  description: "123"
  __proto__: Symbol
    constructor: ƒ Symbol()
    description: "123"
    toString: ƒ toString()
    valueOf: ƒ valueOf()
    Symbol(Symbol.toPrimitive): ƒ [Symbol.toPrimitive]()
    Symbol(Symbol.toStringTag): "Symbol"
    get description: ƒ description()
    __proto__: Object
    [[PrimitiveValue]]: Symbol(123)
typeof b // "object"
b.constructor() // Symbol()
b instanceof Symbol // true
b instanceof Object // true
Object.prototype.toString.call(b) // "[object Symbol]"

4. Передаточная функция строки

1. eval()

let funcStr = "function test(value){alert(value)}";
let test = eval("(false || "+funcStr+")");
test("函数能够执行");

2. new Function()

function add(a, b) {
  return a + b;
}
//等价于
var add = new Function ('a', 'b', 'return a + b');
let funcStr = "function test(value){alert(value)}";
let funcTest = new Function('return '+funcStr);
funcTest()("函数也能够执行")

Четыре,nullа такжеundefinedразница

1,Null

  • nullПредставляет объект «Нет», преобразованный в значение0;
  • Как параметр функции это означает, что параметр функции не является объектом;
  • как конец цепочки прототипов объектов.
  • Number(null)для0
  • 5 + nullкусочек5

2,Undefined

  • Переменная объявлена, но ей не присвоено значение, она равнаundefined;
  • При вызове функции не был указан параметр, который должен быть указан, и параметр равенundefined;
  • Объект не имеет назначенного свойства, значение свойства равноundefined;
  • Когда функция не имеет возвращаемого значения, она возвращает значение по умолчанию.undefined;
  • Number(undefined)дляNaN;
  • 5 + undefinedдляNaN.

Пятерки,typeofа такжеinstanceofразница

1. Основное отличие

  • typeofУказывает на обнаружение типа переменной, за исключением базовых типов данных.nullОбычно он может отображаться как соответствующий тип, а ссылочный тип будет отображаться как функция, кроме функции.function, все остальное будет отображаться какobject;
  • instanceofЭто не объект для обнаружения прототипа цепного прототипа объекта объекта конструктора.

2,typeofправильноnullотображение ошибок

Это просто давняя ошибка в JS. В начальной версии JS использовалась 32-битная система.Из соображений производительности информация о типе переменной хранится в младших битах.Начало 000 представляет объект, но ноль представляет собой все нули, поэтому оценивается неправильно как объект 。

3. Реализуйтеinstanceof

Object.getPrototypeOf():Object.getPrototypeOf()Метод Возвращает прототип указанного объекта (внутренний [[[[Prototype]] значение атрибута).

function myInstance (left, right) {
	let proto = Object.getPrototypeOf(left) // Object.getPrototypeOf() 方法返回指定对象的原型(内部[[Prototype]]属性的值)。
  	while(true) {
  		if (proto === null) return false
	    if (proto === right.prototype) return true
    	proto = Object.getPrototypeOf(proto)
  	}
}

проверять

myInstance([], Object) //true
myInstance(Map, Object) //true
myInstance(new Map(), Object) //true
myInstance(Map, Function) //true
myInstance(class {}, Function) //true
myInstance(1, Number) //true
myInstance('1', String) //true

шесть,this

1. Опишитеthis

Для функции объект, указывающий на последнюю вызывающую функцию, является внутренним объектом, автоматически генерируемым при запуске функции, и может использоваться только внутри функции; для глобального объектаthisнаправлениеwindow.

2, в рамках функцииthisКогда определили?

Когда функция вызывается, она указывает на объект, который был вызван последним

3.call,apply,bindРазница между тремя

Роль трех функций состоит в том, чтобы привязать функцию к контексту и использовать ее для изменения функции.thisуказать на; разница между тремя заключается в различии в синтаксисе.

fun.call(thisArg[, arg1[, arg2[, ...]]])
fun.apply(thisArg, [argsArray])
var bindFn = fun.bind(thisArg[, arg1[, arg2[, ...]]])
bindFn()

applyа такжеcallРазница в том,callМетод принимает несколько списков параметров, иapplyReceived — это массив с несколькими параметрами. а такжеbind()метод создает новую функцию, которая при вызовеthisКлючевому слову присваивается предоставленное значение при вызове новой функции с заданной последовательностью аргументов, поставляемых перед любым из предоставленных.

const name = 'window'
const sayName = function (param) {
    console.log('my name is:' + this.name + ',my param is ' + param)
}
sayName('window param') //my name is:window,my param is window param

const callObj = {
    name: 'call'
}
sayName.call(callObj, 'call param') //my name is:call,my param is call param

const applyObj = {
    name: 'apply'
}
sayName.apply(applyObj, ['apply param']) //my name is:apply,my param is apply param

const bindObj = {
    name: 'bind'
}
const bindFn = sayName.bind(bindObj, 'bind param')
bindFn() //my name is:bind,my param is bind param

4. В чем смысл этого?

  1. Привязка по умолчанию: в глобальной средеthisпо умолчанию привязано кwindow.
  2. Неявное связывание: в общем, при вызове функцией, содержащейся в непосредственном объекте, также известном как вызов метода.thisНеявно привязан к этому непосредственному объекту.
  3. Неявная потеря: неявная потеря означает, что неявно связанная функция теряет связанный объект, поэтому по умолчанию используетсяwindow. Явное связывание: черезcall(),apply(),bind()метод связывает объект сthis, называемое явной привязкой.
  4. newПривязка: если функция или метод вызывается с ключевым словом перед нимnew, который представляет собой вызов конструктора. дляthisпривязка, называемаяnewсвязывать.

this 指向示意图

5. Функция стрелкиthis

  1. Стрелочные функции неthis, поэтому его необходимо определить, просматривая цепочку областей видимостиthis, что означает, что если стрелочная функция содержится в нестрелочной функции,thisПривязка — ближайший слой нестрелочной функцииthis.
  2. Стрелочные функции не имеют собственныхargumentsобъект, но может получить доступ к закрывающей функцииargumentsобъект.
  3. не могу пройтиnewвызов ключевого слова, опять же безnew.targetценности и прототипы.

6. Ручная реализацияcall,applyа такжеbind?

1. call

Function.prototype.myCall = function (thisArg, ...args) {
    const fn = Symbol('fn') // 声明一个独有的 symbol 属性,防止 fn 覆盖已有属性
  	thisArg = thisArg || window // 若没有 this 传入,则绑定 window 对象
  	thisArg[fn] = this // this 指向调用 call 的对象,即我们要改变 this 指向的函数
  	const result = thisArg[fn](...args) // 执行当前函数
  	delete thisArg[fn] // 删除我们声明的 fn
  	return result // 返回函数执行结果
}

2. apply

Function.prototype.myApply = function (thisArg, args) {
    const fn = Symbol('fn') // 声明一个 symbol 
  	thisArg = thisArg || window // 设置 thisArg 
  	thisArg[fn] = this // this 指向改变
  	const result = thisArg[fn](...args) // 执行函数
  	delete thisArg[fn] // 删除 fn
 	return result // 返回结果
}

3. bind

Function.prototype.myBind = function (thisArg, ...args) {
    const self = this
  	const fbound = function () {
    	self.apply(this instanceof self ? this : thisArg,args.concat(Array.prototype.slice.call(arguments)))
  	}
  	fbound.prototype = Object.create(self.prototype)
  	return fbound
}

7. Суждениеthisнаправление

1. obj0.obj.test()

const a = 1
function test () {
    console.log(this.a)
}
const obj = {
    a: 2,
    test
}
const obj0 = {
    a: 3,
    obj 
}
obj0.obj.test() // 2

2. testcopy()

var a = 1
function test () {
    console.log(this.a)
}
const obj = {
    a: 2,
    test
}
const testCopy = obj.test
testCopy() // 1 
// this 指向是在函数执行时确定

3. ВsetTimeoutсередина

var a = 1
function test () {
    console.log(this.a)
}
const obj = {
    a: 2,
    test
}
setTimeout(obj.test) // 1
// this 指向是在函数执行时确定

Семь,JSмодульный

1. Модульный процесс разработки

  • IIFEсамовыполняющаяся функция
  • AMDиспользоватьrequireJSдля написания модульности (зависимости должны быть объявлены заранее).
  • CMDиспользоватьseaJSдля написания модульности (поддерживает динамический импорт файлов зависимостей.)
  • CommonJS nodeJsвстроенная модульность
  • UMDсовместимыйAMD,CommonJSграмматика
  • webpack(require.ensure):webpack 2.xРазделение кода по версиям
  • ES Modules:ES6Представлена ​​модульность, которая поддерживаетimportпредставить еще одинjs
  • scriptЭтикеткаtype="module"

js 模块化

2,AMDа такжеCMDразница

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

  • AMDУважайте предварительную зависимость и объявляйте модули, от которых она зависит, при определении модуля.
  • CMDРодственники тесно зависят, только при использовании модуля.require

3.CommonJSНормативные характеристики

  1. Таким образом, код выполняется в области модуля и не загрязняет глобальную область.
  2. Модули загружаются синхронно, и следующие операции будут выполняться только после загрузки импортированных модулей.
  3. Модули кешируются после первого выполнения, а перезагрузка возвращает только кешированный результат
  4. CommonJSВывод — это копия значения, и изменения внутри модуля не повлияют на значение (есть разница между ссылочными типами и базовыми типами).

4.ES6 modulesКаковы характеристики спецификации

  1. выходное использованиеexport
  2. Введение в использованиеimport
  3. можно использоватьexport ... from ...добиться эффекта перехода
  4. Переменные входного модуля не могут быть переназначены. Просто читаемая ссылка, но свойства могут быть переопределены
  5. exportа такжеimportКоманда находится на верхнем уровне модуля, не может находиться в области видимости, находится в блоке кода и не может быть статически оптимизирована, что нарушаетES6Первоначальный замысел конструкции модуля
  6. importЭффект лифтинга есть, поднимется на голову всего модуля, сначала выполнить
  7. Babelположитexport/importпревратиться вexports/requireформе, поэтому вы можете использоватьexportsа такжеimport

5.CommonJSа такжеES6 Modulesнормативная разница

  1. CommonJSмодули загружаются во время выполнения,ES6Modulesзагружается во время компиляции
  2. CommonJSкопия выходного значения,ES6ModulesСсылка на выходное значение (изменения внутри модуля повлияют на ссылку)
  3. CommonJSМодуль импорта может быть выражением (полезнымrequire()Представляем),ES6ModulesИмпорт может быть только строковым
  4. CommonJSгде это указывает на текущий модуль,ES6Modulesсерединаthisнаправлениеundefined
  5. ES6ModulesНет вarguments,require,module,exports,__filename,__dirnameэти переменные верхнего уровня

6. Как асинхронно загружать модули

AMDа такжеCMDПоддержка асинхронной загрузки модулей

7. Какие вопросы необходимо учитывать при разработке модуля?

  1. безопасность
  2. закрыто
  3. Избегайте конфликтов переменных
  4. изолированная область
  5. Извлечение публичного кода

8,node require(X)Последовательность обработки представила что?

  1. еслиXявляется встроенным модулем, вернитесь к этому модулю и не продолжайте выполнение;
  2. еслиXк'./'、'/'、'../'в начале будет основываться наXРодительский модуль, где он находится, определитеXАбсолютный путь: воляXВ качестве файла нажмите «Найти сейчас», возвращается в файл, больше не продолжается; б. 0.XВ качестве каталога искать файлы в каталоге по очереди, если они существуют, возвращать файл и не продолжать выполнение;
  3. еслиXбез пути: А. СогласноXРодительский модуль, где он находится, определитеXвозможные каталоги установки б. В каждом каталоге по очереди поместитеXЗагрузить в качестве имени имени файла или каталога
  4. бросатьnot foundошибка

9. Взаимные ссылки в узле

имеетa.jsа такжеb.jsдва файла, ссылающиеся друг на друга

1. CommonJS

{
  id: '...',
  exports: { ... },
  loaded: true, parent: null, filename: '', children: [], paths: []
}

CommonJSМодуль — это файл сценария.requireПри первой загрузке сценария команда выполняет весь сценарий и создает объект в памяти. Когда вам понадобится использовать этот модуль в будущем, вы придете кexportsстоимость на имущество. даже если выполнить сноваrequireкоманда, модуль не будет выполняться снова, но значение будет получено из кеша.

CommonJSВажной особенностью является то, что он выполняется во время загрузки, а код скриптаrequire, все выполняются.

CommonJSМетод заключается в том, что после «циклической загрузки» модуля будет выводиться только та часть, которая была выполнена, а часть, которая не была выполнена, не будет выводиться.

// a.js
exports.done = false;
var b = require('./b.js');
console.log('在 a.js 之中,b.done = %j', b.done);
exports.done = true;
console.log('a.js 执行完毕');
//b.js
exports.done = false;
var a = require('./a.js');
console.log('在 b.js 之中,a.done = %j', a.done);
exports.done = true;
console.log('b.js 执行完毕');
  1. a.jsСначала скрипт выводитdoneПеременная, а затем загрузите другой файл сценарияb.js. Обратите внимание, что в это времяa.jsКод останавливается здесь, подождитеb.jsПосле завершения выполнения переходите к следующему выполнению.
  2. b.jsВыполните вторую строку, она загрузитсяa.js, в это время происходит "циклическая загрузка". система пойдетa.jsсоответствующий объект модуляexportsзначение атрибута, но посколькуa.jsеще не закончено, изexportsСвойства могут получить только ту часть, которая была выполнена, а не окончательное значение.
  3. a.jsЧасть, которая была выполнена, представляет собой только одну строку.
exports.done = false;
  1. Следовательно, дляb.js, начинается сa.jsвведите только одну переменнуюdone, значениеfalse.
  2. b.jsЗатем спуститесь вниз и выполните, дождитесь завершения всех исполнений, а затем верните право выполнения наa.js. тогда,a.jsЗатем продолжайте выполнение, пока выполнение не будет завершено. мы пишем сценарийmain.jsи запустите, чтобы проверить процесс.
// main.js
var a = require('./a.js');
var b = require('./b.js');
console.log('在 main.js 之中, a.done=%j, b.done=%j', a.done, b.done);
// 运行
// 在 b.js 之中,a.done = false
// b.js 执行完毕
// 在 a.js 之中,b.done = true
// a.js 执行完毕
// 在 main.js 之中, a.done=true, b.done=true
  1. Приведенный выше код доказывает две вещи. Один вb.jsсреди,a.jsВыполнение не завершено, выполняется только первая строка. два,main.jsКогда вторая строка будет выполнена, она больше не будет выполнятьсяb.js, но вывод кэшируетсяb.js, что является его четвертой строкой.

2. ES6

ES6Механизм работы модуля иCommonJSне то же самое, встречает команду загрузки модуляimportКогда модуль не выполняется, генерируется только ссылка. Подождите, пока он вам действительно понадобится, а затем перейдите к модулю, чтобы получить значение.

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

ES6Ему все равно, происходит ли вообще "циклическая загрузка", он просто создает ссылку на загруженный модуль, что требует от разработчика гарантии того, что значение может быть извлечено, когда значение действительно получено.

// even.js
import { odd } from './odd'
export var counter = 0;
export function even(n) {
  counter++;
  return n == 0 || odd(n - 1);
}
// odd.js
import { even } from './even';
export function odd(n) {
  return n != 0 && even(n - 1);
}

согласно сCommonJSСпецификация не может быть загружена, и будет сообщено об ошибке, ноES6может быть казнен. Это работает, потому чтоES6Загруженные переменные динамически ссылаются на модуль, в котором они расположены. Пока ссылка существует, код выполняется.

$ babel-node
> import * as m from './even.js';
> m.even(10);
true
> m.counter
6
> m.even(20)
true
> m.counter
17

В приведенном выше коде параметрnот10стали0в процессе,foo()будет выполнено всего6раз, поэтому переменнаяcounterравный6. второй звонокeven()когда параметрnот20стали0,foo()будет выполнено всего11раз, плюс предыдущий6раз, поэтому переменнаяcounterравный17.

Восемь,JSмероприятие

1. Что такое делегирование событий

Делегат мероприятия / Делегат мероприятия: Вообще говоря, функция события ответа элемента делегируется его родительскому или внешнему элементу посредством всплытия событий.

недостаток:

  1. Он может поддерживать только всплывающие события и не может быть делегирован для не всплывающих событий (focus/blur )
  2. Все события подвержены ошибкам, предложениям
  3. Внутренний уровень элемента слишком прост, чтобы быть слоем, предотвращающим выход наружу.

2,document,window,html,bodyиерархические отношения

window > document > html > body

  • windowдаBOMОсновной объект , с одной стороны, используется для получения или установки свойств и поведения браузера, с другой стороны, он используется как глобальный объект;
  • documentЭто объект, связанный с документом и имеющий некоторые функции для управления содержимым документа;
  • htmlэлементы иdocumentЭлементные объектыhtmlДокументацияDOMобъект.

3.addEventListenerЧто такое третий параметр функции?

1. бытьbooleanВремя:

  • Третий параметр включает всплытие или захват;
    • дляtrueзахвачен, дляfalseпри бульканье.

2. какObjectВремя:

  • capture:Boolean,Выражатьlistenerбудет распространяться наEventTargetсрабатывает когда.
  • once:Boolean,Выражатьlistener在添加之后最多只调用一次。 еслиtrue,listenerбудет автоматически удален после вызова.
  • passive:Boolean,Установить какtrueкогда, указываяlistenerникогда не звониpreventDefault(). еслиlistenerВсе еще вызывая эту функцию, клиент проигнорирует ее и выдаст консольное предупреждение.
  • mozSystemGroup: только вXBLилиFirefox' chromeиспользовать, этоBoolean,Выражатьlistenerбыл добавлен вsystem group.

4. Специфический процесс пузырения и захвата

пузырь: когда событие привязано к элементу, событие, в свою очередь, будет инициировано в его родительском элементе;захватывать: Прохождение сверху вниз, противоположное пузырению.

<!-- 会依次执行 button li ul -->
<ul onclick="alert('ul')">
  <li onclick="alert('li')">
    <button onclick="alert('button')">点击</button>
  </li>
</ul>
<script>
  window.addEventListener('click', function (e) {
    alert('window')
  })
  document.addEventListener('click', function (e) {
    alert('document')
  })
</script>

пузырь:button -> li -> ul -> document -> windowзахватывать:window -> document -> ul -> li -> button

5. Что такое непузырьковые события?

  • onblur
  • onfoucs
  • onmouseenter
  • onmouseleave

6. Нативные пользовательские события

1. Что такое пользовательские события

  • использоватьEvent
  • использоватьcustomEvent
  • использоватьdocument.createEvent('customEventName')а такжеinitEvent()

2. Создайте собственное событие

1) использоватьEvent
let myEvent = new Event('my_event_name')
2) ИспользованиеcustomEvent
let myEvent = new CustomEvent('my_event_name', {
    detail: {
    // 需要传递的参数
    // 在监听的回调函数中获取到:event.detail
  }
})
3) Использованиеdocument.createEvent('CustomEvent')а такжеinitEvent()
let myEvent = document.createEvent('CustomEvent')
myEvent.initEvent(
    // event_name 是事件名
  // canBubble 是否冒泡
  // cancelable 是否可以取消默认行为
)

3. Мониторинг событий

dom.addEventListener('my_custom_name', function(e) {})

4. Запуск события

dispatchEvent(myEvent)

5. Кейсы

// 1.
let myEvent = new Event('myEvent');
// 2.
let myEvent = new CustomEvent('myEvent', {
  detail: {
    name: 'lindaidai'
  }
})
// 3.
let myEvent = document.createEvent('CustomEvent');
myEvent.initEvent('myEvent', true, true)
let btn = document.getElementsByTagName('button')[0]
btn.addEventListener('myEvent', function (e) {
  console.log(e)
  console.log(e.detail)
})
setTimeout(() => {
  btn.dispatchEvent(myEvent)
}, 2000)

9,JSВнутренние функции и замыкания

1. Что такое замыкание

MDN: Функция связана со ссылками на окружающее ее состояние (лексическое окружение) (или функция окружена ссылками), такая комбинация является замыканием.

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

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

2. Что такое внутренняя функция

Вообще говоря, внутри функции определена другая функция, и такая функция является внутренней функцией.

3, закрытие роли?

  1. Используйте замыкания для доступа к переменным в функциях;
  2. Переменные могут долго храниться в памяти.

4. Утечка памяти

1. Ситуации, вызывающие утечку памяти:

  1. циклическая ссылка
  2. Автоматическое преобразование бокса типа
  3. немногоDOMдействовать

(44. Закрытие

2. Решение проблемы с утечкой памяти:

  1. Ниже приведено преобразование типов, которого можно избежать, показав преобразование типов;
  2. Избегайте циклических ссылок, вызванных событиями;
  3. эксплуатация туалета;
  4. Для ручного удаления переменных;

3. Являются ли утечки памяти заполнением памяти?

нет, даже если1byteпамять, также называемая утечкой памяти.

4. Программа выдает сообщение о нехватке памяти, это утечка памяти?

Нет, обычно это бесконечный рекурсивный вызов функции, который вызывает переполнение памяти стека.

5. Где утечка памяти?

Свайная площадь. Площадь стека не раскрывается

6. Каковы последствия утечек памяти?

В большинстве случаев последствия не очень серьезные. но слишком многоDOMДействия замедляют работу веб-страницы.

7. Перейти на веб-страницу, утечка памяти все еще существует?

И так до закрытия браузера.

десять,EventLoopпроцесс исполнения

1. Кратко опишитеEventLoopпроцесс исполнения

  • весьscriptВыполнить как задачу макроса;
  • Во время выполнения синхронный код выполняется напрямую, макрозадача попадает в очередь макрозадач, а микрозадача входит в очередь микрозадач;
  • После завершения выполнения текущей макрозадачи обнаруживается список микрозадач, и если он есть, выполняется выполнение микрозадач до тех пор, пока не будет выполнен весь список микрозадач;
  • запустить браузерUIРабота с рендерингом потоков;
  • Проверьте, есть лиweb workerзадание, выполнить его;
  • После выполнения этого раунда макрозадач вернитесь ко второму шагу и повторяйте цикл по очереди, пока очереди макрозадач и микрозадач не опустеют.

EventLoop执行顺序

2,requestAnimationFrame

1. Особенности

  1. Вызывается перед повторным рендерингом.
  2. Скорее всего не вызывается после задачи макроса.

2. Зачем вызывать его перед повторным рендерингом?

потому чтоrAFОфициально рекомендуется использовать для некоторых плавных анимаций.API, анимация неизбежно изменитсяDOM, и если вы измените его после рендерингаDOM, то его можно отрисовывать только до следующего раунда возможностей рендеринга, что явно неразумно.

rAFДает вам последний шанс измениться, прежде чем браузер решит отобразитьDOMсвойств, а затем быстро визуализировать их для вас на следующем рисунке, так что это лучший выбор для плавной анимации.

3.requestIdleCallback

requestIdleCallbackМетод ставит в очередь функции, которые вызываются в период простоя браузера. Это позволяет разработчикам выполнять фоновую и низкоприоритетную работу в основном цикле событий, не влияя на критичные к задержке события, такие как анимация и ответы ввода.

1. Отображение в упорядоченном виде

requestIdleCallback1

2. Рендеринг долго простаивает

在这里插入图片描述 50msЭто гарантирует, что пользователь получит ответ без ощутимой задержки.

4.EventLoopЦиклические ноты

  • Цикл событий не обязательно сопровождается тяжелым рендерингом каждый раунд, но если есть микрозадачи, то они будут выполняться вместе с микрозадачами.
  • Есть много факторов, которые определяют, будет ли отображаться представление браузера, и браузеры очень умны.
  • requestAnimationFrameВыполняется перед повторным рендерингом экрана, идеально подходит для анимации.
  • requestIdleCallbackВыполняется после рендеринга экрана, и его свободное выполнение зависит от расписания браузера. Если вы должны выполнить его в течение определенного времени, используйтеtimeoutпараметр.
  • resizeа такжеscrollСобытие на самом деле идет с дросселированием, оно толькоEvent Loopэтап рендеринга для отправки событийEventTargetначальство.

5.forпетля иsetTimeout

существуетforдобавить в циклsetTimeout

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

setTimeout

1. varизменить наlet

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

let

2. Используйте самовыполняющиеся функции

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

自执行函数

3. forИзмените петлю наforEachцикл

[1,2,3,4].forEach(item => {
  setTimeout(() => {
    console.log(item)
  }, 1000)
})

forEach

4. setTimeoutпередать параметры

for (var i = 0; i < arr.length; i++) {
  setTimeout((i) => {
    console.log(arr[i])
  }, 1000, i)
}

setTimeout 传参

5. Прямой вывод

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

直接输出

11,JSсерединаlet,const,var

1,JSСколько существует способов определения переменных?

  • let
  • const
  • var
  • class
  • import
  • function

2,let,const,varКакая разница?

var let const
нет области блока имеет область действия блока имеет область действия блока
объявить глобальные переменные вwindowВниз (под глобальными свойствами) глобальные переменные не находятся под глобальными свойствами Глобальные переменные не находятся под глобальными свойствами
Переопределение переменной не сообщает об ошибке сообщит об ошибке сообщит об ошибке
объявить переменную объявить переменную объявить константу
Есть вариативное продвижение Нет переменного улучшения Нет переменного продвижения
Присвоить значение в любое время после объявления Присвоить значение в любое время после объявления Присвоение сразу после объявления

3.constМожно ли изменить константы определения?

  1. constОпределение базового типа не модифицирована;
  2. constОпределение ссылочного типа позволяет изменять значение в ссылочном типе.

4. Если я хочуconstОпределение ссылочного типа не может изменить его значение, что мне делать?

  1. Object.freeze;
  2. играет роль(proxy/Object.defineProperty);
  3. изменить объектconfigurable,writableАтрибуты.

5. КакES5реализуется в случаеletа такжеconst?

1. Реализацияlet

Можно пройти функции самореализации.

2. Реализацияconst

в состоянии пройтиObject.defineProperty()реализовать, установитьwritable.

двенадцать,JSмножество

1,ES6Новые методы массива

Array.from(),Array.of(),copyWithin(),find(),findIndex(),fill(),entries(),keys(),values(),includes().

2,ES5Добавлен метод массива

forEach(),map(),filter(),some(),every(),indexOf(),lastIndexOf(),reduce(),reduceRight().

3. Какой из этих методов массивов может изменить исходный массив?

copyWithin(),fill(),pop(),push(),reverse(),shift(),sort(),splice().

4.someа такжеeveryКакая разница?

Это видно из китайского значения,someкакой-то,everyкаждый, все они возвращаютBooleanстоимость.

5. В массиве 100 000 элементов данных. Какой из них занимает первый элемент и 100 000-й элемент?

практически одновременно, потому чтоjsВ нем нет типа массива, массив на самом деле является объектом,keyа такжеvalue.

6. Сколько существует способов дедупликации массива?

1. Метод обхода многослойного цикла

  • двойнойforцикл;
  • рекурсивный цикл.

2. Используйте синтаксис самого ключа неповторяемости или API для дедупликации

  • ES6 Setубрать вес;
  • Создайте новый пустой объект для дедупликации;
  • Однослойная петля +filter/includes/indexOf;
  • Однослойная петля +Map,ObjectИди потяжелее.

7.forпетля иforEachКакое исполнение лучше?

forЦиклы работают лучше

  • forЦикл не имеет дополнительного стека вызовов функций и контекста;
  • forEachне обычныйforСинтаксический сахар цикла, и есть много параметров и контекстов, которые необходимо учитывать во время выполнения, что может снизить производительность.

8,sortКаким образом сортируется сортировка?

Порядок сортировки по умолчанию заключается в преобразовании элементов в строки и последующем сравнении ихUTF-16когда построена последовательность значений кодовой единицы.

9. Преобразование многомерного массива в одномерный массив

  • reduceрекурсивная реализация
  • joinа такжеsplitвыполнить
  • рекурсивный обход
  • flatметод
  • toStringа такжеsplitвыполнить
  • Обход в ширину/обход в глубину

10. Как реализовать обход в ширину и обход в глубину

JS обход в глубину и обход в ширину

1. Обход в глубину

  • посетить вершинуv;
  • в порядке отvНачиная с непосещенных соседних точек , граф проходится в глубину до тех пор, пока граф иvПосещаются вершины с одинаковым путем;
  • Если на пути остаются непосещенные вершины, начиная с непосещенной вершины, обход в глубину выполняется снова, пока не будут посещены все вершины.
const depth = (node) => {
    let stack = []
    let nodes = []
    if (node) {
        stack.push(node)
        while (stack.length) {
            //每次取最后一个
            let item = stack.pop()
            let children = item.children || []
            nodes.push(item)
            //判断children的长度
            for (let i = children.length - 1; i >= 0; i--) {
                stack.push(children[i])
            }
        }
    }
    return nodes
}

2. Обход в ширину

  • Создайте очередь и поместите начальный узел в очередь;
  • Если очередь не пуста, берем первый узел из очереди и проверяем, является ли он целевым узлом;
  • Если это целевой узел, завершить поиск и вернуть результат;
  • Если нет, добавьте в очередь все необнаруженные байты;
  • Если очередь пуста, что указывает на отсутствие целевого узла в графе, обход завершается.
const breadth = (node) => {
    let nodes = []
    let stack = []
    if (node) {
        stack.push(node)
        while (stack.length) {
            //取第一个
            let item = stack.shift()
            let children = item.children || []
            nodes.push(item)
            for (let i = 0; i < children.length; i++) {
                stack.push(children[i])
            }
        }
    }
    return nodes
}

11. Реализуйтеreduce

Array.prototype.myReduce = function (fn, init) {
    if (!init && this.length === 0) { // 如果数组长度为0
        return this
    }
    let start = 1, pre = this[0]; // 从数组第二个开始下标为1
    if (init !== undefined) { // 如果 init 字段存在,从第一个开始,下标为 0
        start = 0;
        pre = init;
    }
    for (let i = start; i < this.length; i++) { // 循环
        let current = this[i]
        pre = fn.call(this, pre, current, i, this) // 把每次的 reduce 的值返回
    }
    return pre
}

12. Реализовать алгоритм случайного перемешивания массива

function disOrder2 (arr) {
    for (let i = 0; i < arr.length; i++) { // 遍历
        const randomIndex = Math.floor(Math.random() * ary.length) // 生成随机数
        swap(arr, i, randomIndex)
    }
}
function swap(arr, i, _i) { // 交换
    const tem = arr[i]
    arr[i] = arr[_i]
    arr[_i] = tem  
}
arr = [1,2,3,4,5,6,7,8]
disOrder(arr)
console.log(arr)

13. Добавьте запятые в строку чисел

1. Обычный

num.replace(/(\d)(?=(\d{3})+(\.|$))/g, "$1,")

2. Траверс

function formatNumber(num) {
  if (!num) return "";
  let [int, float] = num.split(".");
  let intArr = int.split("");
  let result = [];
  let i = 0;
  while (intArr.length) {
    if (i !== 0 && i % 3 === 0) {
      result.unshift(intArr.pop() + ",");
    } else {
      result.unshift(intArr.pop());
    }
    i++;
  }
  return result.join("") + "." + (float ? float : "");
}

14.map,find,every,some,forEachЧто делает второй параметр метода etc?

arr.every(callback(element[, index[, array]])[, thisArg])
  • thisArg

воплощать в жизньcallbackиспользуется, когдаthisстоимость.

Тринадцать,for inа такжеfor ofКакая разница?

Сравнивать for in for of
разница Может перемещаться по обычным объектам
Обход объекта-прототипа массива
Вы можете перемещаться по собственным свойствам массива
Пройденное значение равноkey
нельзя пройтиmap/set
не повторяемыйgenerators
поддержка IE
не может проходить через обычные объекты
Не пересекает объект-прототип
не пересекает свои собственные свойства
Пройденное значение равноvalue
можно пройтиmap/set
повторяемыйgenerators
ИЕ не поддерживает
Та же точка обход массива
Могуbreakпрервать обход
обход массива
Могуbreakпрервать обход

четырнадцать,Promise

1. Как реализоватьsleepфункция (функция задержки)

пройти черезpromiseа такжеsetTimeoutпросто реализовать

/**
 * 延迟函数
 * @param {Number} time 时间
 */
function sleep (time = 1500) {
    return new Promise((resolve) => {
        setTimeout(() => {
            resolve(true)
        }, time)
    })
}

2,promiseКонструктор,thenметод,catchметод,finallyКакой метод асинхронный, а какой синхронный?

promiseКонструктор выполняется синхронно,then,catchа такжеfinallyМетоды выполняются асинхронно.

3. Как отменитьpromise?

отменить обещание

1. Используйтеpromise.race()

  • Promise.race(iterable)

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

/**
* @author guoqiankunmiss
*/
//封装一个取消promise的函数,使用promise.race的特性
function stopPromise (stopP) {
	let proObj = {};
	let promise = new Promise((resolve, reject) => {
		proObj.resolve = resolve;
		proObj.reject = reject;
	})
	proObj.promise = Promise.race([stopP, promise])
	return proObj
}
//一个5秒钟之后执行的.then方法的promise
let promise = new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve(123);
    }, 5000);
});
//调用函数
let obj = stopPromise(promise);
//收集返回值
obj.promise.then(res => {
    console.log(res);
});
//两秒钟之后进行取消promise操作
setTimeout(() => {
	obj.resolve("Promise 请求被取消了!");
}, 2000)

4. НесколькоpromiseКак добиться первого успехаpromise?

Получите первое успешное обещание среди нескольких обещаний

1. Promise.allУлучшать

использоватьpromise.allособенности, обходpromiseМассив, оцениваемый по возвращаемому значению, в случае успеха преобразуется вrejectвернуться, в случае неудачи обратиться кresolveВперед, продолжать.

//第一个成功的Promise
function firstProSuccess (allProMise) {
  //遍历promise数组,根据返回值进行判断,当成功的时候,转为reject返回,当失败的时候转为resolve继续执行。
  return Promise.all(allProMise.map(item => {
    return item.then(
      res => Promise.reject(res),
      err => Promise.resolve(err)
    )
  })).then(
    errors => Promise.reject(errors),
    val => Promise.resolve(val)
  )
}

2. Promise.any

  • Promise.any(iterable)

получитьPromiseсовокупность объектов, когда один изpromiseВ случае успеха вернуть тот, что удалосьpromiseценность .

недостаток: Есть проблемы с совместимостью

5. Несколькоpromise,всеpromiseПолучить возвращаемый результат (возвращаемое значение независимо от успеха/неудачи)

1. Promise.allУлучшать

Аналогично описанному выше принципу, за исключением того, что операция не выполняется в случае ее успеха.rejectкогдаresolveдействовать

2. Promise.allSettled()

  • Promise.allSettled(iterable)

возвращает во всех заданныхpromiseужеfulfilledилиrejectedПослеpromise.

недостаток: Есть проблемы с совместимостью

6. Расскажите оpromiseЧто такое статические методы?

1. Promise.all(iterable)

получитьpromiseобъект массива (итерируемыйpromiseобъект экземпляра), когда все успешно, вернуть всеpromiseКоллекция массивов; при сбое одного из них вернуть текущий сбойpromiseобъект.

2. Promise.allSettled(iterable)

получитьpromiseОбъект массива, вернуть новый, когда все завершено (независимо от успеха/неудачи)promiseколлекция массивов

3. Promise.any(iterable)

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

4. Promise.race(iterable)

получитьpromiseОбъект массива, когда любой из них преуспевает/не удается, возвращаетpromiseстоимость

5. Promise.reject(reason)

возвращает статус неудачиPromiseобъект.

6. Promise.resolve(value)

Возвращает статус, заданныйvalueрешенныйPromiseобъект.

7. Promise.finally(onFinally)

в текущемpromiseВызывается после запуска, независимо от текущегоpromiseСтатус завершен(fulfilled) или провал(rejected )

8. Promise.try(f)

Принимает функцию и возвращаетpromise.

Предоставляет единый механизм обработки для всех операций, поэтому, если вы хотите использоватьthenпроцесс управления методом, лучше всего использоватьPromise.tryУпакуйте это.

  • улучшенная обработка ошибок
  • лучшая совместимость
  • легко ориентироваться

Promise-try

7.Promise.thenВы понимаете второй параметр ? а также.catchКакая разница?

then()метод возвращаетPromise.

Принимает не более двух параметров:PromiseФункция обратного вызова для условий успеха и отказа.

p.then(onFulfilled[, onRejected]);
p.then(value => {
  // fulfillment
}, reason => {
  // rejection
});

Второй параметр также является функцией, которая является функцией обратного вызова для состояния отказа.

thenвторой параметр catch
thenпараметры метода Promiseметод экземпляра
thenПервый параметр выдает исключение, которое не было перехвачено. Первый параметр then генерирует исключение, которое можно перехватить.
это функция СутьthenСинтаксический сахар для методов
Если второй параметр иcatchодновременно существуют,promiseВнутренняя ошибка, второй параметр может быть захвачен В настоящее время,catchНе может захватывать, второй параметр не существует,catchБудет захвачен
Не рекомендуется для использования Рекомендуется использоватьcatchПерехват ошибок

8,Promise.resolveСколько ситуаций?

1. Параметр представляет собойPromiseпример

параметрPromiseнапример, тогдаPromise.resolveЭтот экземпляр будет возвращен без изменений и без изменений.

2. Параметр представляет собойthenableобъект

Promise.resolve()метод преобразует этот объект вPromiseобъект, а затем немедленно выполнитьthenableобъектthen()метод.

3. Параметр не имеетthen()объект метода или вообще не объект

Если параметр является примитивным значением или параметром, который не имеетthen()объект метода, затемPromise.resolve()метод возвращает новыйPromiseобъект, состояниеresolved.

4. Без каких-либо параметров

непосредственно вернутьresolvedсостояниеPromiseобъект.

9. Если.thenПараметр in не является функцией, и что?

Promise.resolve(1)
    .then(2)
    .then(console.log)
// 1

если.thenаргументы не являются функциями, они внутренне заменены на(x) => x, то есть вернуть как естьpromiseФункция конечного результата.

10. Если.finallyПоследовать.then, то этоthenКакая ценность внутри?

Promise.resolve('resolve')
  .finally(() => {
    console.log('this is finally')
    return 'finally value'
  })
  .then(res => {
    console.log('finally后面的then函数, res的值为:', res)
  })
// this is finally

finallyНазадthenфункция,resЗначение:resolve

  1. finallyФункция обратного вызова не получает никаких параметров;
  2. существуетpromiseконец, каким бы ни был результатfulfilledилиrejected, выполнитfinallyПерезвоните;
  3. finallyвозвращает предыдущийPromiseстоимость объекта.

11..allа также.raceБудут ли продолжать выполняться другие асинхронные задачи, когда во входящем массиве возникнет первое исключение?

Да, это будет продолжаться, но не вthen / catchпроявляется в.

Браузер выполняет следующий код, вы можете видеть, что когда сообщается об ошибкеconsoleОн продолжит выполняться, но не будет отображаться в соответствующей функции обратного вызова.

function sleep (n) {
    return new Promise((resolve, reject) => {
        console.log(n)
        Math.random() > 0.5 ? reject(n) : resolve(n)
    }, n % 2 === 0 ? 1000 * n : 1000)
}
Promise.all([sleep(1), sleep(2), sleep(3)])
  .then(res => console.log('all res: ', res))
  .catch(err => console.log('all err:', err))
Promise.race([sleep(1), sleep(2), sleep(3)])
  .then(res => console.log('race res: ', res))
  .catch(err => console.log('race err:', err))

12..allЭто параллельно или последовательно?

является параллельным, но возвращаемое значение иpromise.allПолученные массивы находятся в том же порядке.

13.promiseПочему возможна цепочка

потому чтоthen,catch,finallyметод вернет новыйpromise, поэтому позволяет нам связывать вызовы.

14.async/await

1. Принцип реализации

asyncфункция основана наgeneratorреализация, поэтому она включаетgeneratorсвязанная информация. В отсутствиеasyncперед функцией обычно используютcoбиблиотека для выполненияgenerator, так чтоcoМы также можем смоделироватьasyncреализация.

2. Простая реализация

1)coбиблиотека
function Asyncfn() {
  return co(function*() {
    //.....
  });
}
function co(gen) {
  return new Promise((resolve, reject) => {
    const fn = gen();
    function next(data) {
      let { value, done } = fn.next(data);
      if (done) return resolve(value);
      Promise.resolve(value).then(res => {
        next(res);
      }, reject);
    }
    next();
  });
}
2)GeneratorФункции и самоисполнители
function spawn(genF) {
    return new Promise(function(resolve, reject) {
        const gen = genF();
        function step(nextF) {
            let next;
            try {
                next = nextF();
            } catch (e) {
                return reject(e);
            }
            if (next.done) {
                return resolve(next.value);
            }
            Promise.resolve(next.value).then(
                function(v) {
                    step(function() {
                        return gen.next(v);
                    });
                },
                function(e) {
                    step(function() {
                        return gen.throw(e);
                    });
                }
            );
        }
        step(function() {
            return gen.next(undefined);
        });
    });
}

пятнадцать, скажемJSON.stringifyа такжеJSON.parse

1,JSON.stringify

определение: поставитьJavaScriptобъект или значение преобразуется вJSONнить. Параметры: есть три параметра

JSON.stringify(value[, replacer [, space]])
  1. replacer

replacerПараметр может быть функцией или массивом. Как функция она принимает два параметра, ключ (key) и значение (value), все они будут сериализованы.replacerпредставляет собой массив, представление значений которого будет сериализовано вJSONСтроковое имя свойства. 2.space spaceПараметры используются для управления интервалом в результирующей строке. Если это число, каждый уровень будет иметь больший отступ, чем предыдущий уровень при строковом преобразовании; Если это строка, каждый уровень будет отступать от строки больше, чем предыдущий уровень.

2,JSON.parse

Определение: используется для разбораJSONнить. Параметры: есть два параметра

JSON.parse(text[, reviver])
  1. reviver

Преобразователь, если он передается в этом параметре (функции), может использоваться для изменения исходного значения, сгенерированного синтаксическим анализом.

характеристика

  1. Преобразовать значение, если оно естьtoJSON()метод, который определяет, какое значение будет сериализовано.
  2. Не гарантируется, что свойства объектов, не являющихся массивами, появятся в сериализованной строке в определенном порядке.
  3. Булевы, числовые и строковые объекты-обертки автоматически преобразуются в соответствующие примитивные значения во время сериализации.
  4. undefined, любую функцию иsymbolзначение, либо игнорируемое при сериализации (при наличии в значениях свойств объектов, не являющихся массивами), либо преобразуемое вnull(при наличии в массиве). функция,undefinedПри индивидуальном преобразовании возвращаетсяundefined,Такие какJSON.stringify(function(){}) or JSON.stringify(undefined).
  5. Выполнение этого метода для объектов, содержащих циклические ссылки (объекты, ссылающиеся друг на друга, образующие бесконечный цикл), вызовет ошибку.
  6. все сsymbolАтрибуты, являющиеся ключами атрибутов, полностью игнорируются, даже если параметр-заменитель принудительно включает их.
  7. Dateдата называетсяtoJSON()преобразовать его вstringстрока (такая же, какDate.toISOString()), поэтому он обрабатывается как строка.
  8. NaNа такжеInfinityзначение формата иnullбудет рассматриваться какnull.
  9. другие типы объектов, в том числеMap/Set/WeakMap/WeakSet, будут сериализованы только перечисляемые свойства.

шестнадцать,==,===а такжеObject.is()

1. Разница

  • ==Когда типы значений на обеих сторонах различаются, сначала выполняется преобразование типов, а затем выполняется сравнение.
  • ===Без преобразования типов, прямое сравнение значений
  • Object.is(val1, val2)Проверить, совпадают ли два значения

2,==Как работает преобразование типов?

  1. Если типы разные, выполните преобразование типов
  2. определить, является ли сравнениеnullилиundefined, если да, вернутьtrue
  3. Определить, является ли типstringилиnumber, если да, то будетstringПеревести вnumber
  4. определить, является ли один изboolean, если да, включите один изnumberвынесение суждений
  5. определить, является ли один изobject, а другая сторонаstring,number,symbol, если да, то будетobjectПреобразование в примитивный тип для суждения (valueOf()метод)
  6. если одинNaN, затем вернитесь напрямуюfalse
  7. Если оба являются объектами, сравните, указывают ли они на один и тот же объект

==比较

3.[] == ![]Какова ценность?

Отвечать:дляtrue

Шаги конверсии

  1. Оператор ! имеет наивысший приоритет,![]будет преобразован вfalse, так что это время[] == false
  2. В соответствии со статьей 4 одна из сторонboolean,ПучокbooleanПеревести вnumber, так что это время[] == 0
  3. Тогда по статье 5 ставим массив[]Преобразовать в примитивный тип, вызвать массивtoString()метод,[].toString() = '', так что это время'' == 0
  4. Согласно статье 3,stringПеревести вnumber,''Перевести вnumberравно 0, так что на этот раз0 == 0
  5. Обе стороны имеют одинаковый тип данных0 == 0,дляtrue

4. Object.is() оценивает ситуацию, когда два значения равны

без принуждения

  • обеundefined
  • обеnull
  • обеtrueилиfalse
  • все строки одинаковой длины с одинаковыми символами в одном и том же порядке
  • являются одним и тем же объектом (это означает, что каждый объект имеет одну и ту же ссылку)
  • все числа и
    • обе+0
    • обе-0
    • обеNaN
    • или оба отличны от нуля и неNaNи такое же значение

Семнадцать, анти-тряска и дросселирование

1. Что такое анти-шейк и троттлинг

Стабилизатор: несколько выполнений изменены на последнее выполнениедросселирование: это изменение многократного выполнения на выполнение через равные промежутки времени.

2. Простая реализация антитряски и троттлинга

1. Реализация защиты от сотрясений

Идеи:После запуска высокочастотного событияnФункция будет выполняться только один раз в секунды, еслиnВысокочастотное событие в секундах срабатывает снова, затем пересчитайте время и отмените предыдущий метод вызова задержки каждый раз, когда событие срабатывает.

function debounce (fn, time = 500) {
  let timeout = null; // 创建一个标记用来存放定时器的返回值
  return function () {
    clearTimeout(timeout) // 每当触发时,把前一个 定时器 clear 掉
    timeout = setTimeout(() => { // 创建一个新的 定时器,并赋值给 timeout
      fn.apply(this, arguments)
    }, time)
  }
}
function testDebounce () {
  console.log('测试防抖')
}
const inp = document.getElementById('testInp')
inp.addEventListener('input', debounce(testDebounce))

2. Реализация регулирования

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

function throttle (fn, time = 100) {
  let timeout;
  return function () {
    let context = this
    let args = arguments
    if (!timeout) {
      timeout = setTimeout(() => {
        timeout = null
        fn.apply(context, args)
      }, time)
    }
  }
}
function testThro () {
  console.log('测试节流')
}
const inp = document.getElementById('testInp')
inp.addEventListener('input', throttle(testThro))

18,cookie,sessionStorageа такжеlocalStorage

1. Разница между тремя

  • cookieИспользуется для сохранения регистрационной информации, размер ограничен4KBо
  • localStorageдаHtml5Недавно добавленные, используемые для локального хранения данных, сохраненные данные не имеют срока действия, а общий размер браузера ограничен5MB
  • sessionStorageметоды интерфейса иlocalStorageАналогично, но сохраненные данные будут сохранены только в текущем сеансе и будут очищены после закрытия страницы.
имя Продолжительность жизни предельный размер общаться с сервером Можно ли пересечь домен
cookie Как правило, генерируется сервером, время истечения срока действия может быть установлено. Если генерируется на стороне браузераCookie, по умолчанию срок действия истекает после закрытия браузера 4KB всегда носить с собойHTTPзаголовок, если используетсяcookieСохранение слишком большого объема данных может привести к проблемам с производительностью В общем нет, то же самоеdomainСледующие запросы интерфейса могут быть разрешены для переносаcookie
localStorage Постоянный, если не очищен 5MB Сохранение только в браузере, без связи с сервером невозможно
sessionStorage Действует только для текущего сеанса, очищается после закрытия страницы или браузера 5MB Сохранение только в браузере, без связи с сервером невозможно

2,localStorageКак выполнить междоменное хранение?

localStorageНевозможно выполнять междоменные операции, но если вы хотите выполнять междоменные операции, вы можете использоватьpostMessage,websocketВыполнять скрытые междоменные операции.

Девятнадцать, междоменные проблемы браузера

1. Что такое политика браузера с одинаковым происхождением?

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

так называемыйТа же политика происхождения, который относится только к адресам в:

  1. имя протокола
  2. доменное имя
  3. имя порта

разрешен доступ к одному и тому жеcookie,localStorageи страница доступаDOMили отправитьAjaxпросить.

2. Какие опасные сценарии без ограничения политики одного и того же происхождения?

  • ajxaпросить
  • Domзапрос

Политика того же происхождения действительно может избежать некоторых опасностей.Это не означает, что политика того же происхождения безопасна, но что политика того же происхождения является самым основным механизмом безопасности для браузеров.В конце концов, это может увеличить стоимость атак .

3. Почему браузеры запрещают междоменный доступ?

  • Кроссдоменность существует только на стороне браузера, потому что форма браузера очень открыта, и ее нужно ограничивать.
  • Политика того же происхождения используется для защиты пользовательской информации и предотвращения злонамеренной кражи данных (ajaxполитика того же происхождения,DomТа же политика происхождения).

4. Какие существуют решения для междоменного доступа?

Междоменное решение проблем CSDN

  1. jsonp
  2. cors
  3. postMessage
  4. websocket
  5. NodeПрокси промежуточного ПО (дважды междоменный)
  6. nginxобратный прокси
  7. window.name + iframe
  8. location.hash + iframe
  9. document.domain + iframe

5.CORSОбщая конфигурация Что?

  • Access-Control-Allow-OriginРазрешенное доменное имя
  • Access-Control-Allow-MethodsРазрешаетсяhttpметод запроса
  • Access-Control-Allow-HeadersПоддерживаемые заголовки запросов
  • Access-Control-Allow-Credentialsотправлять лиcookie
  • Access-Control-Max-Ageвремя кэширования в секундах

6.CORSПроцесс междоменного принятия решения

  1. Браузер сначала определяет, является ли это одним и тем же источником, если это одно и то же происхождение, он отправляет данные напрямую, в противном случае он отправляет междоменный запрос;
  2. После того, как сервер получает междоменный запрос, он возвращает соответствующий заголовок файла в соответствии со своей конфигурацией;
  3. Браузер получает заголовок ответа в соответствии сAccess-Control-Allow-originЕсли такого поля, указывающего на то, что междоменное использование не разрешено, нет, будет сообщено об ошибке.Если это поле присутствует, оно будет сравнено, чтобы определить, возможно ли междоменное взаимодействие.

7. Что такое простой запрос?

Простой запрос — это запрос, отвечающий следующим условиям:

  • использоватьget,post,headодин из способов сделать запрос;
  • httpИнформация заголовка не превышает следующих условий:
    • Accept
    • Accept-Language
    • Content-Language
    • Last-Event-ID

Content-Type: значение ограниченоapplication/x-www-form-urlencoded,multipart/form-data,text/plain

  • просьбаXMLHttpRequestUploadОбъект не имеет зарегистрированных прослушивателей событий;
  • XMLHttpRequestUploadобъект может использоватьXMLHttpRequest.uploadдоступ к собственности. не используется в запросеReadableStreamобъект.

8. Непростой запрос

Запросы, которые имеют особые требования к серверу (отличные от простых запросов, являются непростыми запросами).

Например: метод запросаput,delete,Content-TypeТипapplication/json.

Непростые запросы будут использоваться перед официальным общениемoptionsИнициируйте предварительный запрос, запрашивая у сервера, находится ли текущее доменное имя в списке разрешенных сервером, и какие поля заголовка использовать.

9. Какие методы можно использовать для встраивания ресурсов из разных источников?

  • scriptтеги, встроенный междоменный скриптинг;
  • linkтеги, встроенныеcss;
  • imgтеги, встроенные изображения;
  • video/audioтеги, встроенное видео, аудио;
  • object/embed/appletтеги, встроенныеsvg/картинка и т. д.;
  • svgтеги, встроенныеsvg;
  • пройти через@font-faceвстроенный шрифт;
  • пройти черезiframeВстроить ресурсы

10. Вручную внедрить одинJSONP

//Promise封装
function jsonp({ url, params, callback }) {
  return new Promise((resolve, reject) => {
    // 创建 script 标签
    let script = document.createElement('script')
    // 把 callback 挂载在 window 上,执行之后删除 script 
    window[callback] = function(data) {
      resolve(data)
      document.body.removeChild(script)
    }
    // 添加参数
    params = { ...params, callback } // wd=b&callback=callFun
    let arrs = []
    for (let key in params) {
      arrs.push(`${key}=${params[key]}`)
    }
    // 设置 script 的 URL
    script.src = `${url}?${arrs.join('&')}`
    // 插入 body 中
    document.body.appendChild(script)
  })
}
// 调用示例
jsonp({
  url: 'http://localhost:3000/code',
  params: { wd: 'hello world' },
  callback: 'callFun'
}).then(data => {
  console.log(data) // 你好啊
  //再此回调结束后删除该script
})

Двадцать, скажемjsМетод наследования

Шесть распространенных методов наследования в JS

1. Наследование цепочки прототиповprototype

Прототипом подтипа является экземпляр объекта супертипа.

Child.prototype = new Parent()

преимущество:

  1. Простое наследование
  2. Новые методы родительского класса, свойства, подклассы могут получить доступ к

недостаток:

  1. Множественное наследование невозможно
  2. Все свойства родительского класса являются общими для всех экземпляров.
  3. Чтобы добавить свойства и методы в подкласс, он должен быть после Child.prototype = new Parent(), потому что он будет перезаписан
  4. При создании подкласса нельзя передавать параметры, как у родительского класса

2. Наследование конструктораcall

Общее в конструкторе подтипаcall()вызвать конструктор супертипа

function Child(name, age, price) {
    Parent.call(this, name, age)  // 相当于: this.Parent(name, age)
}

преимущество:

  1. Проблема экземпляров подклассов, совместно использующих свойства ссылки на родительский класс в наследовании цепочки прототипов
  2. При создании экземпляра подкласса вы можете передавать параметры родительскому классу
  3. Может достигать множественного наследования (вызывать несколько объектов родительского класса)

недостаток:

  1. Экземпляр не является экземпляром родительского класса, а является экземпляром дочернего класса.
  2. Может наследовать только свойства и методы экземпляра родительского класса, но не свойства и методы прототипа.
  3. Повторное использование функций невозможно, каждый подкласс имеет копию функции экземпляра родительского класса, что влияет на производительность.

3. Комбинированное наследование цепочки прототипов + конструкторprototype + call

Вызовите родительский класс для создания, наследования свойств родительского класса и сохранения преимуществ передачи параметров, а затем используйте экземпляр родительского класса в качестве прототипа дочернего класса для повторного использования функций.

function Child (name, age, price) {
  Parent.call(this, name, age)
}
Child.prototype = new Parent()
Child.prototype.constructor = Child//组合继承也是需要修复构造函数指向的

преимущество:

  1. Свойства/методы экземпляра могут быть унаследованы, как и свойства/методы прототипа.
  2. Нет проблемы с совместным использованием эталонного свойства
  3. Сносно

недостаток:

  1. Конструктор родительского класса вызывается дважды, и создаются два экземпляра.

4. Комбинированная оптимизация наследования 1

Указав на один и тот же объект между прототипом родительского класса и прототипом подкласса, подкласс может наследовать общедоступные методы родительского класса как свои собственные общедоступные методы и не будет дважды инициализировать методы/свойства экземпляра, избегая недостатков комбинированного наследования.

function Child (name, age, price) {
    Parent.call(this, name, age)
}
Child.prototype = Parent.prototype

преимущество:

  1. не позвонит конструктору родительского класса дважды

недостаток:

  1. Невозможно различить, создан ли экземпляр подклассом или суперклассом, и конструкторы подкласса и суперкласса указывают на одно и то же.

5. Комбинированная оптимизация наследования 2

С помощью прототипов объекты могут создаваться на основе существующих объектов,var B = Object.create(A)кAОбъект является прототипом, который генерируетBобъект.BнаследоватьAВсе свойства и методы .

function Child (name, age, price) {
    Parent.call(this, name, age)
}
Child.prototype = Object.create(Parent.prototype)
Child.prototype.constructor = Child

6.es6 classнаследование

classКлючевые слова — это просто синтаксический сахар для прототипов,JavaScriptНаследование по-прежнему осуществляется на основе прототипов.

class Parent {
    constructor(name, age) {
        this.name = name
        this.age = age
    }
    setName () {
        console.log('parent')
    }
}
let child1 = new Parent('name1', 18)
let child2 = new Parent('name2', 16)
class Child extends Parent {
    constructor(name, age, price) {
        super(name, age)
        this.price = price
    }
    setAge () {
        console.log('子类方法')
    }
}
let child3 = new Child('name3', 20, 15000)
let child4 = new Child('name4', 21, 10000)

преимущество:

  1. простое наследование

Двадцать один, алгоритм сортировки

1. Пузырьковая сортировка

Проще говоря, это сравнение двух соседних элементов, и замена позиции по нужному вам методу сортировки (по возрастанию или по убыванию) При замене требуется дополнительная переменная в качестве промежуточной переменной для временного хранения значения.冒泡排序

function bubbleSort(arr) {
    var len = arr.length;
    for (var i = 0; i < len; i++) {
        for (var j = 0; j < len - 1 - i; j++) {
            if (arr[j] > arr[j+1]) {        //相邻元素两两对比
                var temp = arr[j+1];        //元素交换
                arr[j+1] = arr[j];
                arr[j] = temp;
            }
        }
    }
    return arr;
}

2. Быстрая сортировка

Выберите датум, поместите меньшую датум слева, а меньшую датум справа (база находится посередине)快速排序

function quickSort(arr) {
    //如果数组<=1,则直接返回
    if (arr.length <= 1) { return arr; }
    var pivotIndex = Math.floor(arr.length / 2);
    //找基准,并把基准从原数组删除
    var pivot = arr.splice(pivotIndex, 1)[0];
    //定义左右数组
    var left = [];
    var right = [];
    //比基准小的放在left,比基准大的放在right
    for (var i = 0; i < arr.length; i++) {
        if (arr[i] <= pivot) {
            left.push(arr[i]);
        }
        else {
            right.push(arr[i]);
        }
    }
    //递归
    return quickSort(left).concat([pivot], quickSort(right));
}

3. Сортировка выбором

Сначала найдите наименьшие элементы из исходного массива и массива элементов спереди, затем найдите наименьший элемент из остальной части элемента, наименьший элемент сзади, пока не будет отсортирован.选择排序

function selectionSort(arr) {
    var len = arr.length;
    var minIndex, temp;
    for (var i = 0; i < len - 1; i++) {
      minIndex = i;
      for (var j = i + 1; j < len; j++) {
        if (arr[j] < arr[minIndex]) {
          minIndex = j;
        }
      }
      temp = arr[i];
      arr[i] = arr[minIndex];
      arr[minIndex] = temp;
    }
    return arr;
}

4. Сортировка вставками

Начиная со второго элемента (при условии, что первый элемент уже отсортирован), возьмите этот элемент, сравните отсортированные элементы сзади наперед, и, если элемент больше этого элемента, переместите элемент на следующую позицию, а затем продолжите сравнивать вперед до тех пор, пока не будет найдена позиция, меньшая или равная элементу, и элемент будет вставлен в эту позицию. Повторяйте этот шаг, пока сортировка не будет завершена.插入排序

function insertionSort(arr) {
  var len = arr.length;
  var preIndex, current;
  for (var i = 1; i < len; i++) {
    preIndex = i - 1;
    current = arr[i];
    while (preIndex >= 0 && arr[preIndex] > current) {
      arr[preIndex + 1] = arr[preIndex];
      preIndex--;
    }
    arr[preIndex + 1] = current;
  }
  return arr;
}

5. Сортировка слиянием

Сортировка слиянием — это эффективный алгоритм сортировки, основанный на операции слияния. Алгоритм использует метод «разделяй и властвуй» (Divide and Conquer) — очень типичное приложение. Сортировка слиянием является стабильным методом сортировки. Объедините упорядоченные подпоследовательности, чтобы получить полностью упорядоченную последовательность, то есть сначала сделайте каждую подпоследовательность упорядоченной, а затем сделайте упорядоченными сегменты подпоследовательности. Если два отсортированных списка объединяются в один отсортированный список, это называется двусторонним слиянием.归并排序

function mergeSort(arr) {  //采用自上而下的递归方法
    var len = arr.length;
    if(len < 2) {
        return arr;
    }
    var middle = Math.floor(len / 2),
        left = arr.slice(0, middle),
        right = arr.slice(middle);
    return merge(mergeSort(left), mergeSort(right));
}
function merge(left, right){
    var result = [];
    console.time('归并排序耗时');
    while (left.length && right.length) {
        if (left[0] <= right[0]) {
            result.push(left.shift());
        } else {
            result.push(right.shift());
        }
    }
    while (left.length)
        result.push(left.shift());
    while (right.length)
        result.push(right.shift());
    console.timeEnd('归并排序耗时');
    return result;
}

6. Сортировка по холму

Используйте размер шага для выполнения попарного сравнения, а затем уменьшите размер шага для сортировки. Описание: Суть сортировки Хилла заключается в групповой сортировке вставками, которую также называют сортировкой с нарастанием сжатия. Основная идея этого метода заключается в следующем: сначала разделить всю последовательность сортируемых элементов на несколько подпоследовательностей (состоящих из элементов, разделенных определенным «приращением») для прямой сортировки вставками, а затем перед сортировкой поочередно уменьшать приращения, с этим Когда элементы в последовательности в основном упорядочены (приращение достаточно мало), выполните прямую сортировку вставкой для всех элементов. Поскольку прямая сортировка вставками очень эффективна, когда элементы в основном упорядочены (близко к лучшему случаю), сортировка Хилла обеспечивает большее улучшение временной эффективности. Отличия от сортировки вставками:Он будет предпочтительно сравнивать элементы, которые находятся дальше 希尔排序

function shellSort(arr) {
  let temp,
    gap = 1;
  while (gap < arr.length / 3) {
    gap = gap * 3 + 1//动态定义间隔序列
  }
  for (gap; gap > 0; gap = Math.floor(gap / 3)) {//控制步长(间隔)并不断缩小
    for (var i = gap; i < arr.length; i++) {//按照增量个数对序列进行排序
      temp = arr[i]
      for (var j = i - gap; j >= 0 && arr[j] > temp; j -= gap) {//例:j=0  arr[1]>arr[5]
        arr[j + gap] = arr[j]
      }
      arr[j + gap] = temp
    }
  }
  return arr
}

7. Сравнение различных алгоритмов сортировки

算法比较

Двадцать два, временная сложность, пространственная сложность

1. Как измерить плюсы и минусы разных алгоритмов?

В основном он рассматривается из двух измерений «времени» и «пространства», занимаемых алгоритмом.

  • Измерение времени: относится ко времени, которое требуется для выполнения текущего алгоритма, которое мы обычно описываем как «временную сложность».
  • Пространственное измерение: это относится к тому, сколько памяти требуется для выполнения текущего алгоритма.Мы обычно описываем его как «пространственная сложность».

2. Временная сложность

1. Метод представления

"Обозначение большого O",которыйT(n) = O(f(n))

Формула временной сложности:T(n) = O( f(n) )f(n)представляет собой сумму количества выполнений каждой строки кода, иOПредставляет пропорциональную зависимость Полное название этой формулы: асимптотическая временная сложность алгоритма.

2. Общие показатели сложности

• Постоянный порядокO(1)• ЛогарифмическийO(logN)• Линейный порядокO(n)• Линейный логарифмический порядокO(nlogN)• Квадратный порядокO(n²)• Кубический порядокO(n³)• K-й порядок мощностиO(n^k)• Экспоненциальный порядок(2^n)

3. O(1)

Независимо от того, сколько строк кода выполняется, пока нет сложных структур, таких как циклы, временная сложность этого кодаO(1)

var i = 1;
var j = 2;
++i;
j++;
var m = i + j;

4. O(n)

forКод внутри цикла будет выполнятьсяnВо всем, чтобы он потреблял с изменением N, поэтому такой код можно использовать.O(n)для представления его временной сложности.

for(i=1; i<=n; ++i)
{
   j = i;
   j++;
}

5. Логарифмический порядокO(logN)

var i = 1;
while(i<n)
{
    i = i * 2;
}

существуетwhileВнутри цикла каждый разiумножить на2, после умноженияiрасстояниеnстановится ближе. Давайте попробуем решить его, скажем, циклxПосле раз,iбольше, чем2В этот момент цикл завершается, т. е.2изxмощность равнаn,Такx = log2^nТо есть, когда петляlog2^nПо истечении этого времени код заканчивается. Таким образом, временная сложность этого кода:O(logn)

6. O(nlogN)

Временная сложностьO(logn)Если код повторяется N раз, то его временная сложность равнаn * O(logN), то есть,O(nlogN).

for(m=1; m<n; m++)
{
    i = 1;
    while(i<n)
    {
        i = i * 2;
    }
}

7. O(n²),O(m*n),O(n³),O(n^k)

Квадратный заказO(n²)ПучокO(n)Код снова вкладывает цикл, и его временная сложность равнаO(n*n),Прямо сейчасO(n²).

for(x=1; i<=n; x++)
{
   for(i=1; i<=n; i++)
    {
       j = i;
       j++;
    }
}

O(m*n)петелька одного из слоевnизменить наm, то его временная сложность становитсяO(m*n)

for(x=1; i<=m; x++)
{
   for(i=1; i<=n; i++)
    {
       j = i;
       j++;
    }
}

3. Пространственная сложность

Сложность пространства — это мера размера памяти, временно занятой алгоритмом во время выполнения процесса, а также отражающая тенденцию.S(n)определять.

1. Общие показатели сложности

Наиболее часто используемая пространственная сложность:O(1)、O(n)、O(n²).

2. O(1)

Если временное пространство, необходимое для выполнения алгоритма, не следует за переменнойnРазмер , то есть объемная сложность этого алгоритма, является константой, которую можно выразить какO(1)

var i = 1;
var j = 2;
++i;
j++;
var m = i + j;

в кодеi,j,mВыделенное пространство не меняется в зависимости от объема обрабатываемых данных, поэтому его объемная сложностьS(n) = O(1)

3. O(n)

var arr = [1, 2, 3]
for(i=1; i<=arr.lemgth; ++i)
{
   j = i;
   j++;
}

Первая строка определяет массив, и размер, занимаемый этими данными, равенn, этот код2-6Строка, хоть и есть цикл, но новое место не выделяется, поэтому объемная сложность этого кода в основном зависит от первой строки, т.е.S(n) = O(n)

23. Запрос интерфейса

1,AJAX

1. Простая реализацияajax

function stringify (json) {
  var str = "";
  for (var i in json) {
    str += i + "=" + json[i] + "&";
  }
  return str.slice(0, -1);
}
function myAjax (type, url, params, callback, errback) {
  let xhr = null;
  //表IE
  if (window.XMLHttpRequest) {
    xhr = new XMLHttpRequest();
  } else {
    xhr = new ActiveXObject("Microsoft.XMLHTTP");
  }
  if (type == "get") {
    xhr.open(type, url + "?" + stringify(params), true);
    xhr.send();
  } else {
    xhr.open(type, url, true);
    xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
    //json转换成name=张三&age=1
    xhr.send(stringify(params));
  }
  xhr.onreadystatechange = function () {
    // 表示请求已完成
    if (xhr.readyState == 4) {
      if (xhr.status == 200) {
        if (callback) {
          callback(xhr.responseText);
        }
      } else {
        errback && errback();
      }
    }
  }
}

2,ajaxизreadyStateположение дел

  • 0неинициализированный, еще не вызванныйopen()метод
  • 1начало, называетсяopen()метод, но не вызываетсяsend()метод
  • 2отправил, позвонилsend()метод, но пока не получил ответа
  • 3Прием, данные частичного ответа получены
  • 4Готово, все данные ответа получены

2,Axios

AxiosПо сути роднойXHRпакет, за исключением того, чтоPromiseверсия реализации, соответствующая последнимESТехнические характеристики

1. Особенности:

  • отnode.jsСоздайтеhttpпросить
  • служба поддержкиPromise API
  • Поддержка клиентов предотвращаетCSRF
  • Предоставляет некоторые интерфейсы для одновременных запросов (важно, удобно для многих операций)

3.Fetch

Fetch APIпредоставилJavaScriptинтерфейс для доступа и управленияHTTPЧасти конвейера, такие как запросы и ответы. Он также предоставляет глобальнуюfetch()метод, который обеспечивает простой и разумный способ асинхронной выборки ресурсов по сети.

1. Преимущества

  • Лаконичный синтаксис, более семантический
  • основанный на стандартахPromiseРеализация, поддержкаasync/await
  • Изоморфный удобен в использованииisomorphic-fetch

2. Недостатки

  • FetchЗапрос по умолчанию неcookieДа, нужно установитьfetch(url, {credentials: 'include'})
  • Сервер не возвращает коды ошибок 400, 500reject, только когда сетевые ошибки приводят к сбою запроса,fetchбудетreject.

двадцать четыре,newоператор

1,newпроцесс реализации

  • 1. Создайте новый объект;
  • 2. Назначьте область действия конструктора новому объекту (такthisуказывает на этот новый объект);
  • 3. Выполните код в конструкторе (добавьте свойства для этого нового объекта);
  • 4. Верните новый объект.
  • 5. Ставим конструкторprototypeсвязанный с экземпляром__proto__

2. Как реализоватьnew

function myNew (foo, ...args) {
  // 创建一个新对象,并继承 foo 的 prototype 属性
    let obj = Object.create(foo.prototype)
  // 执行构造方法,并绑定新 this,
  let result = foo.apply(obj, args)
  // 如果构造方法返回了一个对象,那么就返回该对象,否则就返回 myNew 创建的新对象
  return Object.prototype.toString().call(result) === '[object Object]' ? result : obj
}

25. Как реализовать полноэкранный режим веб-страницы?

document.documentElement.requestFullscreen()

Требуется совместимая реализация

1. Полноэкранный режим веб-страницы

function fullScreen() {
    if (!document.fullscreenElement &&
        !document.mozFullScreenElement && !document.webkitFullscreenElement && !document.msFullscreenElement) { // current working methods
        if (document.documentElement.requestFullscreen) {
            document.documentElement.requestFullscreen();
        } else if (document.documentElement.msRequestFullscreen) {
            document.documentElement.msRequestFullscreen();
        } else if (document.documentElement.mozRequestFullScreen) {
            document.documentElement.mozRequestFullScreen();
        } else if (document.documentElement.webkitRequestFullscreen) {
            document.documentElement.webkitRequestFullscreen(Element.ALLOW_KEYBOARD_INPUT);
        }
    }
}

2. Отмените полноэкранный режим веб-страницы.

function exitFullScreen() {
    if (document.exitFullscreen) {
        document.exitFullscreen();
    } else if (document.msExitFullscreen) {
        document.msExitFullscreen();
    } else if (document.mozCancelFullScreen) {
        document.mozCancelFullScreen();
    } else if (document.webkitExitFullscreen) {
        document.webkitExitFullscreen();
    }
}

3. Проверьте, является ли он полноэкранным

/**
 * 检查是否全屏
 * @return {[Boolean]} [是否全屏,为 true 没有全屏,false 全屏]
 */
function checkFullScreenValue () {
    return !document.fullscreenElement &&
        !document.mozFullScreenElement && !document.webkitFullscreenElement && !document.msFullscreenElement
}

Двадцать шесть,Map,WeakMapа такжеset,WeakSetКакая разница?

WeakMapа такжеWeakSetслабые ссылки

1. Что такое слабая ссылка

слабая ссылкаСсылается на ссылку, которая не может гарантировать, что объект, на который она ссылается, не будет собран сборщиком мусора, другими словами, он может быть собран в любое время.

Слабые ссылки исчезнут в любой момент, а механизм обхода не может гарантировать существование членов.

2,Set

  • Порядок обхода: порядок размещения
  • Ключа нет, есть только значение, ключ и значение можно считать равными
  • добавить несколькоNaNкогда есть только одинNaN
  • При добавлении одного и того же объекта он будет рассматриваться как другой объект.
  • При добавлении значения (5 !== "5")
  • keys()а такжеvalues()вести себя точно так же,entries()Возвращенный итератор содержит как ключ, так и значение, и два значения равны

3.weakSetэффект

  • а такжеSetСтруктура похожа, значение члена может быть только объектом
  • хранитьDOMузел:DOMЭтот элемент автоматически освобождается при удалении узла, не беспокойтесь об утечке памяти при удалении этих узлов из документа.
  • Временно хранить набор объектов или хранить информацию, привязанную к объектам: пока эти объекты исчезают извне,WeakSetСсылки в структуре автоматически удаляются
  • Все элементы являются слабыми ссылками, которые не учитываются механизмом сборки мусора.WeakSetссылка структуры на этот элемент
  • Член не подходит для ссылки, он исчезает в любой момент, поэтомуES6РегулированиеWeakSetСтруктура не проходима
  • Когда другие объекты больше не ссылаются на этот элемент, механизм сборки мусора автоматически освобождает память, занятую этим элементом, независимо от того, существует ли еще этот элемент в памяти.WeakSetв структуре

4.Map

  • Порядок обхода: порядок размещения
  • Назначьте несколько назначений одной и той же клавише, более позднее значение перезапишет предыдущее значение.
  • ссылка на тот же объект, рассматриваемый как ключ
  • Два экземпляра одного и того же значения рассматриваются как два ключа
  • Ключ привязан к адресу памяти, если адрес памяти отличается, он считается двумя ключами.
  • добавить несколько кNaNВ качестве ключа будет толькоNaNзначение как ключ
  • Objectструктуры обеспечивают соответствие строкового значения,MapСтруктура обеспечивает соответствие «ценность-значение».

5.WeakMap

  • а такжеMapПодобные по структуре ключи-члены могут быть только объектами
  • хранитьDOMузел:DOMЭтот ключ-член автоматически высвобождается при удалении узла, не беспокойтесь об утечке памяти при удалении этих узлов из документа.
  • Развертывание частных свойств: внутренние свойства являются слабыми ссылками на экземпляры и исчезают при удалении экземпляра, не вызывая утечек памяти.
  • Все ключи-члены являются слабыми ссылками, которые не учитываются механизмом сборки мусора.WeakMapсоздать ссылку на этот ключ члена
  • Ключ участника не подходит для ссылки, он исчезает в любой момент, поэтомуES6РегулированиеWeakMapСтруктура не проходима
  • Когда другие объекты больше не ссылаются на ключ члена, механизм сборки мусора автоматически освободит память, занятую этим членом, независимо от того, существует ли этот член еще в памяти.WeakMapв структуре
  • Как только член больше не нужен, член автоматически исчезнет, ​​нет необходимости вручную удалять ссылку
  • Слабые ссылки относятся только к ключам, а не к значениям, а значения по-прежнему являются обычными ссылками.
  • Даже если ключ элемента разыменован извне, внутреннее значение элемента сохраняется.

6.ObjectПеревести вMap

let obj = {"a":1, "b":2};
let map = new Map(Object.entries(obj))

Двадцать семь,Proxy

1. Грамматика

  • targetнужно использоватьProxyОбернутый целевой объект (может быть объектом любого типа, включая собственные массивы, функции или даже другой прокси-сервер).
  • handlerОбъект, обычно с функциями в качестве свойств, для настройки поведения перехвата.

Агент будет толькоproxyОбъект вступает в силу и не влияет на прокси-объект

origin = {}
obj = new Proxy(origin, {
  get: function (target, propKey, receiver) {
        return '10'
  }
});
obj.a // 10
obj.b // 10
origin.a // undefined
origin.b // undefined

2,HandlerОбычно используемые методы объектов

метод описывать
handler.has() inЛовушка оператора.
handler.get() Ловец для операций чтения свойств.
handler.set() Ловец для операций установки свойств.
handler.deleteProperty() deleteЛовец для оператора.
handler.ownKeys() Object.getOwnPropertyNamesМетоды иObject.getOwnPropertySymbolsловец метода.
handler.apply() Ловец для операций вызова функции.
handler.construct() newловушка оператора
### 3.proxyМожно ли отозвать прокси?
proxyимеет единственный статический метод,Proxy.revocable(target, handler)
Proxy.revocable()метод может использоваться для создания отзывного прокси-объекта
Возвращаемое значение этого метода — объект, структура которого следующая: {"proxy": proxy, "revoke": revoke}
  • proxyПредставляет сам только что сгенерированный прокси-объект и обычным способомnew Proxy(target, handler)Созданный прокси-объект ничем не отличается, за исключением того, что его можно отозвать.
  • revokeМетод отзыва, когда вызов не требует никаких аргументов, вы можете отозвать этот прокси-объект, и он будет сгенерирован вместе.
const target = { name: 'vuejs'}
const {proxy, revoke} = Proxy.revocable(target, handler)
proxy.name // 正常取值输出 vuejs
revoke() // 取值完成对proxy进行封闭,撤消代理
proxy.name // TypeError: Revoked //已撤销

28. Контекст выполнения

1. Каков тип контекста выполнения?

1. Глобальный контекст выполнения:

В программе может существовать только один глобальный контекст выполнения.

Это самый простой контекст выполнения по умолчанию. Код, которого нет ни в одной функции, находится в глобальном контексте выполнения. Он делает две вещи:

  1. Создайте глобальный объект, который в браузереwindowобъект.
  2. БудуthisУказатель на этот глобальный объект.

2. Контекст выполнения функции:

Контекстов выполнения функций может быть бесконечное количество.

Каждый раз, когда вызывается функция, для этой функции создается новый контекст выполнения. Каждая функция имеет свой собственный контекст выполнения, но он создается только при вызове функции.

3. EvalКонтекст выполнения функции:

jsизevalФункция, которая выполняет код внутри себя, создает свой собственный контекст выполнения, который редко используется и не рекомендуется.

2, характеристики контекста выполнения

  1. одинарная нить;
  2. Синхронное выполнение, выполняемое последовательно сверху вниз;
  3. Существует только один глобальный контекст, которыйwindowобъект;
  4. Количество контекстов выполнения функции не ограничено;
  5. Функция создается только при ее вызове, и каждый раз при ее вызове создается новый контекст выполнения.

3. Жизненный цикл контекста выполнения

1. Этап создания

  1. Создайте переменный объект: сначала инициализируйте параметры функцииarguments, объявления функций подъема и объявления переменных.
  2. Создать цепочку областей: цепочка областей создается после объекта переменной. Сама цепочка областей видимости содержит переменные объекты. Цепочка областей видимости используется для разрешения переменных. Когда вас попросят разрешить переменную,JavaScriptВсегда начинайте с самого внутреннего уровня вложенности кода.Если переменная не найдена на самом внутреннем уровне, она перейдет к родительской области предыдущего уровня для поиска, пока переменная не будет найдена.
  3. КонечноthisУкажите на: ОКthisуказывает на.

2. Фаза выполнения

  1. Выполните присвоение переменной.
  2. ссылка на функцию.
  3. Выполнить другой код.

3. Стадия переработки

  1. Контекст выполнения всплывает
  2. Ожидание повторного использования контекста выполнения виртуальной машиной.

4.jsКак управлять несколькими контекстами выполнения?

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

Функции: ЛИФО (LIFO:last-in, first-out)Структура.эффект: сохраняет все контексты выполнения во время выполнения кода.

Пример:

var a = 1; // 1. 全局上下文环境
function bar (x) {
    console.log('bar')
    var b = 2;
    fn(x + b); // 3. fn上下文环境
}
function fn (c) {
    console.log(c);
}
bar(3); // 2. bar上下文环境

执行上下文

29. Реализовать некоторые специальные функции

1. Одноразовая функция

function once (func) {
  let done;
  return function () {
    if (!done) {
      func.apply(null, arguments)
      done = true
    }
  }
}
const onlyDoOne = once(function() {
  console.log('1')
})
onlyDoOne() // 1
onlyDoOne() // 没有输出,不会再次执行

2. Функция задержки (функция сна)

function sleep (time) {
    return new Promise(resolve => {
    window.setTimeout(resolve, time)
  })
}
// 调用
sleep(1000).then(res => {
    console.log('延迟')
})
// 调用
async function useSleep () {
    const sleepval = await sleep(1000)
}
useSleep()

3.setTimeoutвыполнитьsetInterval

;(() => {
  const list = new Set();
  function myInterval(fn, ms) {
    const ref = {};
    const exec = () => {
      return setTimeout(() => {
        fn.apply(null);
        const timer = exec();
        ref.current = timer;
      }, ms);
    };
    ref.current = exec();
    list.add(ref);
    return ref;
  }
  function myClearInterval(ref) {
    clearTimeout(ref.current);
    list.delete(ref);
  }
  window.myInterval = myInterval;
  window.myClearInterval = myClearInterval;
})()
myInterval(() => {console.log(1)}, 5000)
myClearInterval({current: 1186})

4. Фронтенд-генерацияexcelсформировать и скачать

/**
 * 前端下载表格
 * @param  {[Array]} data      [数据数组]
 * @param  {[String]} tableHead [表头字符串]
 * @return {[undefined]}           
 */
function downExcel (data, tableHead) {
  tableHead = tableHead
  data.forEach(item => {
    for (let i in item) {
      tableHead += `${item[i] + '\t'},`
    }
    tableHead += '\n'
  })
  const url = 'data:text/csv;charset=utf-8,\ufeff' + encodeURIComponent(tableHead);
  //通过创建a标签实现
  const link = document.createElement("a");
  link.href = url;
  //对下载的文件命名
  link.download = "我的EXCEL表格.csv";
  document.body.appendChild(link);
  link.click();
  document.body.removeChild(link);
}
// excel 数据
let tableData = [{
  name: '你好啊',
  time: 130000000000,
  pre: '127.130',
  source: '淘宝',
  otherTime: 1571276232000
}]
// excel 头部
let str = `用户名,时间,坐标,来源,授权时间\n`;
// 下载表格执行
downExcel(tableData, str)

30. Что такое прототип и цепочка прототипов?

прототип:JSПри объявлении конструктора (функции, используемой для создания экземпляра объекта) в памяти создается соответствующий объект, который является прототипом исходной функции.

Конструктор имеет значение по умолчаниюprototypeАтрибуты,prototypeЗначение указывает на прототип функции. В то же время прототип также имеетconstructorАтрибуты,constructorЗначение указывает на исходную функцию.

Объекты, созданные с помощью конструкторов, не имеютprototypeсвойство, которое по умолчанию имеет__proto__Атрибуты,__proto__Значение указывает на прототип объекта конструктора. Свойства, добавленные или измененные в объекте-прототипе, являются общими для всех созданных объектов.

原型原型链При доступе к свойству в созданном объекте он сначала будет искать внутри объекта, если не будет найден, он будет искаться.__proto__Ищите указанный прототип, если он все еще не найден, переходите к прототипу.__proto__Искать в указанном родительском архетипе до тех пор, пока не будет найдено илиObject.prototypeПока этот цепной процессСеть прототипов.

Тридцать один, осознайте одинEventBus

Простая реализация

class myEventBus {
  constructor(props) {
    this.events = {}
  }
  on (event, fn) {
    const events = this.events
    events[event] ? events[event].push(fn) : (events[event] = [fn])
  }
  emit (event, ...res) {
    this.events[event] && this.events[event].forEach(fn => {
      return fn.apply(this, res)
    })
  }
  remove (event, fn) {
    if (this.events[event]) {
      delete this.events[event]
    }
  }
}

Тридцать два,jsвывоз мусора (GC)

1,V8лимит памяти

  • 1,4 ГБ оперативной памяти для 64-битной системы
  • 0,7 ГБ памяти для 32-битной системы

2,V8управление памятью

  • JSобъекты проходят черезV8Выделять и управлять памятью
  • process.memoryUsage()Возвращает объект, содержащийNodeИнформация об использовании памяти процесса

3. Структурная схема занятости памяти

内存占用图

  • var a = {name:‘yuhua’};Этот код выполнит следующие шаги:
    • Поместите этот код в «область кода»Code Segment"
    • поместите переменнуюaположить в "стек"(Stack): локальная переменная, указатель"
    • Буду{name:‘yuhua’}положить в "HeapTotal(куча): объект, замыкание"
  • Примечание. Базовые типы данных находятся в стеке, ссылочные типы — в куче.

4. Зачем ограничивать объем памяти

  • потому чтоV8Из-за принципа работы сборки мусора для завершения сборки мусора 1,4 ГБ памяти требуется более 1 с.
  • Этот период сборки мусора (время паузы) становитсяStop The World, в течение которого производительность и скорость отклика приложения ухудшаются

5.V8механизм сбора мусора

  • V8основан на поколенческой сборке мусора
  • Разные поколения имеют разные механизмы сборки мусора и разные алгоритмы.
  • По времени инвентаризации он делится на новое поколение и старое поколение.

6. Генерация

  • Молодое поколение – это новое поколение, состоящее изFromплощадь иToРайон состоит из двух зон
  • В 64-битной системе память нового поколения составляет 32 МБ,Fromплощадь иToКаждая область занимает 16M
  • В 32-битной системе память нового поколения составляет 16 МБ,Fromплощадь иToКаждая область занимает 8M
  • Старшее поколение — это старое поколение по умолчанию:
    • Память старого поколения под 64-битной системой 1400M
    • Память старого поколения под 32-битной системой 700M

7. Новое поколение принимаетScavengeалгоритм

ScavengeАлгоритм, используемый для нового поколения, представляет собой алгоритм сборки мусора, реализованный посредством репликации.

Сканирование нового поколения — это стратегия сканирования в ширину.

Он делит память наfromа такжеtoдва пространства. каждый разgc, будуfromЖивые объекты пространства копируются вtoпространство. Затем роли двух пространств меняются местами (т. е. меняются местами).

Этот алгоритм жертвует пространством ради времени, поэтому он подходит для нового поколения, потому что его жизненный цикл объекта короткий.

1. Процесс

  • Зона нового поколения разделена на две части, каждая по 16 м, одну используемую и одну свободную.
  • Когда начинается сборка мусора, он проверяетFROMЖивой объект в регионе, если он еще жив, копируется вTOПространство, освобождаемое (освобождаемое) после копирования всех уцелевших объектовFROMплощадь
  • Затем поля ОТ и Кому меняются местами.

2. Особенности

  • Сканирование нового поколения — это стратегия сканирования в ширину.
  • Космос нового поколения мал, и уцелевших объектов мало
  • Когда диспетчер объектов еще жив после многократных сборок мусора, объекты с плохим временем жизни будут перемещены на старые голосовые связки.Этот процесс перемещения называется продвижением или продвижением.
  • После более чем 5 переработок все еще существуют
  • TOболее 25% используемого пространства или очень большие объекты
  • браузерmemoryВы можете сделать снимок, чтобы увидеть, является ли переменная сборщиком мусора.
  • установлен вundefinedилиnullоба уменьшают количество ссылок на 1

8. Старое поколение принимаетMark-Sweepа такжеMark-Compact

1. Основы

  • Существует два типа стратегий сборки мусора старого поколения.
    • mark-sweepпометить как очищенный
      • Отметьте живые объекты, хотя очищайте объекты, которые не отмечены на этапе маркировки, очищайте только мертвые объекты
      Проблемы, которые возникнут: после очистки память не является непрерывной, а фрагментированная память не может быть выделена
    • mark-compactразметка
      • После пометки мертвых объекты будут отсортированы, живые будут перемещены влево, а память за границей (мертвые объекты) будет очищена после завершения перемещения.
  • Старое поколение имеет большое пространство, и большинство из них являются живыми объектами.GCкропотливый
  • существуетGCНе могу думать о прослушивании в этот период,STOP-THE-WORLD
  • V8Есть схема оптимизации, пошаговая обработка, замена одной большой паузы несколькими маленькими паузамиINCREMENT-GC
  • То есть большая пауза разбивается на несколько маленьких пауз, после каждой паузы приложение какое-то время работает, так что сборка мусора и приложение выполняются попеременно, и время паузы можно сократить примерно до 1/6.

2. Процесс

Допустим есть 10 размеров памяти, а память занимает 6,

1)Mark-SweepСборка мусора шаблонов:
  • Затем каждый объект будет отмечен:
A   b   C   d   E   f  空  空 空 空
//对上面每个对象做上标记,大写表示活着,小写表示死了
//这时候,会存在一个问题,就是内存碎片无法使用,因为小写的内存没有跟后面空空空空的内存放在一起,不能使用
  • В это время строчные (мертвые) будут уничтожены, а будут сохранены только прописные (живые), что вызывает проблему невозможности использования фрагментации памяти.
2)Mark-Compactсборка мусора шаблонов
  • двигаться влево
A C E b d f 空 空 空 空
  • Затем восстановить мертвую зону
A C E 空 空 空 空 空 空 空

9. Сравнение трех алгоритмов

алгоритм утилизации Mark-Sweep Mark-Compact Scavenge
скорость Средняя самый медленный самый быстрый
пространство над головой немного немного Двойное пространство (без фрагментации)
перемещать ли объект нет да да
  • V8В основном используется старым поколениемMark-Sweep,потому чтоMark-CompactОбъекты нужно перемещать и выполнение не быстрое. Используйте, когда места недостаточноMark-Compact

Тридцать три, шаблоны проектирования

1. Принципы проектирования:

1. Принцип единой ответственности (SRP)

Объект или метод делает только одну вещь.

2. Принцип наименьшего знания (LKP)

Взаимодействие между объектами должно быть сведено к минимуму.

3. Принцип открытого-закрытого (OCP)

Программные объекты (классы, модули, функции) и т. д. должны быть расширяемыми, но не модифицируемыми.

2. Режим стратегии

Шаблон стратегии относится к определению серии алгоритмов, инкапсулируя каждый алгоритм и делая их взаимозаменяемыми. Шаблон стратегии позволяет изменять алгоритм независимо от клиентов, использующих его.преимущество:

  • Шаблон стратегии использует методы и идеи, такие как композиция и делегирование, чтобы избежать многих условных операторов if.
  • Шаблон стратегии реализует принцип открытого-закрытого, что упрощает понимание и расширение кода.

Пример:

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

3. Режим кэш-прокси

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

Кэширующий прокси должен кэшировать ранее использованное значение, и если оно все еще используется позже, оно будет использоваться напрямую.

4. Заводской режим

Фабричный шаблон является одним из наиболее распространенных шаблонов проектирования, используемых для создания объектов. Мы не выставляем конкретную логику создания объектов, а инкапсулируем логику в функцию, тогда эту функцию можно рассматривать как фабрику. Фабричный шаблон можно разделить на: простую фабрику, фабричный метод и абстрактную фабрику в зависимости от степени абстракции.

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

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

Шаблон абстрактной фабрики не генерирует экземпляры напрямую, а используется для создания кластеров классов продуктов.

5. Одноэлементный режим

Гарантирует наличие только одного экземпляра класса и предоставляет к нему глобальную точку доступа.

гарантирует, что существует только один экземпляр

  • Поскольку существует только один экземпляр, он экономит системные ресурсы, помните, что создание и уничтожение также тратит ресурсы памяти.
  • Избегает многократного использования ресурсов, таких как соединения с базой данных
  • Обмен ресурсами

Сценарии внешнего интерфейса:

  • браузерwindowобъект. существуетJavaScriptВ процессе разработки для таких объектов, которым нужен только один объект, часто используется одноэлементная реализация.
  • Слои масок, посадочные окна и т. д.

6. Прокси-режим

Предоставляет суррогат или заполнитель для объекта для управления доступом к нему.

Существует три основных режима прокси:Прокси защиты, виртуальные прокси, кеширующие прокси

7. Режим итератора

Шаблон итератора относится к предоставлению способа последовательного доступа к элементам агрегатного объекта без раскрытия внутреннего представления объекта.

JSв массивеmap forEachИтераторы уже встроены

8. Модель «публикация-подписка»

Также известный как паттерн Observer, он определяет зависимость между объектами по принципу «один ко многим».При изменении состояния объекта все зависящие от него объекты будут уведомлены.

События в JS — это реализация классического шаблона публикации-подписки.

9. Командный режим

Разработайте программу слабосвязанным образом, чтобы отправитель запроса и получатель запроса могли устранить взаимосвязь между собой. Заказ(command) относится к инструкции сделать что-то конкретное

Тридцать четыре, функция и самовыполняющаяся функция

1. Особенности самоисполняющихся функций

  1. В отличие от объявлений функций, функциональные выражения допустимы только внутри этой функции, и эта привязкапостоянная привязка.
  2. Чтобы присвоить значение константе, вstrictВ режиме будет сообщение об ошибке, неstrictТихий сбой в режиме.
  3. IIFEФункции в являются функциональными выражениями, а не объявлениями функций.

2. Тип функции

  1. объявление функции
  2. функциональное выражение
  3. создание конструктора функций

1. Объявление функции (FD)

  1. имеет конкретное имя
  2. Расположение в исходном коде: либо на уровне программы (Program level), либо в теле другой функции (FunctionBody)середина
  3. Создано при входе в стадию контекста
  4. Воздействовать на переменный объект
  5. объявить следующим образом
function funName () {}

2. Функциональные выражения (FE)

  1. Должен стоять на позиции выражения в исходном коде.
  2. имеет необязательное имя
  3. Не влияет на переменные объекты
  4. Создается на этапе выполнения кода
// 函数表达式
var foo = function () {} // 匿名函数表达式赋值给变量foo
var foo2 = function _foo2() {} // 外部FE通过变量“foo”来访问——foo(),而在函数内部(如递归调用),有可能使用名称“_foo”。
// 圆括号(分组操作符)内只能是表达式
(function foo() {});
// 在数组初始化器内只能是表达式
[function bar() {}];
// 逗号也只能操作表达式
1, function baz() {};
// !
!function() {}();
(function foo() {})() // 自执行函数 IIFE
(function () {})() // IIFT
var foo = {
  bar: function (x) {
    return x % 2 != 0 ? 'yes' : 'no';
  }(1)
};
foo.bar // 'yes'

3. Функции, созданные конструктором функций

мы связываем это сFDа такжеFEдифференцировать. Главной особенностью этой функции является то, что [[Scope]] содержит только глобальные объекты

var x = 10;
function foo() {
  var x = 20;
  var y = 30;
  var bar = new Function('alert(x); alert(y);');
  bar(); // 10, "y" 未定义
}

3. Как создать функцию, которая может выполняться без ()

  1. создать объект
  2. Выражение в объекте определяет самовыполняющуюся функцию
var foo = {
  bar: function (x) {
    return x % 2 != 0 ? 'yes' : 'no';
  }(1)
};
foo.bar // 'yes'

4. Почему некоторые должны быть добавлены()Можно ли опустить некоторые?

Когда функция не находится в позиции выражения, требуются круглые скобки оператора группировки, то есть функция вручную преобразуется вFE.

Если синтаксический анализатор знает, что имеет дело сFE, нет необходимости использовать скобки.

5. Выражения именованных функций

Когда функциональное выражениеFEимеет имя (называемое именованным функциональным выражением, сокращенноNFE), появляется важная особенность.

Из определения (как мы видели из примера выше) мы знаем, что выражение функции не влияет на объект переменной контекста (это означает, что его нельзя вызвать по имени ни до объявления функции, ни после объявления). но,FEПри рекурсивном вызове можно вызывать себя по имени.

(function foo(bar) {
  if (bar) {
    return;
  }
  foo(true); // "foo" 是可用的
})();

"foo"Где хранится?fooв активном объекте? Нет, потому что вfooне определяет никакого" вfoo". создается в объекте родительской переменной контекстаfoo? Ни то, ни другое, потому что по определению…FEЭто не повлияетVO(переменный объект) - вызывается извнеfooМы действительно можем это видеть. Так где?

Когда интерпретатор встречает названныйFEкогда, вFEПеред созданием он создает вспомогательные специфические объекты и добавляет их в начало текущей цепочки областей видимости. затем он создалFE, и в этот момент (как мы узнали из главы 4, Цепочка областей действия) функция получает [[Scope]] — цепочка областей видимости, создающая контекст этой функции). После этогоFEдобавляется к определенному объекту как уникальное свойство; значение этого свойства является ссылкой наFEначальство. Последний шаг — удалить этот конкретный объект из цепочки родительских областей.

6. Примеры самовыполняющихся функций

// 例一
+function foo(){
foo=10;//我的问题代码
    console.log(foo);//方法自己
}();
console.log(typeof foo);//undefined 观察是否全局污染

// 例二
var b = 10;
(function b() {
   // 内部作用域,会先去查找是有已有变量b的声明,有就直接赋值20,确实有了呀。发现了具名函数 function b(){},拿此b做赋值;
   // IIFE的函数无法进行赋值(内部机制,类似const定义的常量),所以无效。
  // (这里说的“内部机制”,想搞清楚,需要去查阅一些资料,弄明白IIFE在JS引擎的工作方式,堆栈存储IIFE的方式等)
    b = 20;
    console.log(b); // [Function b]
    console.log(window.b); // 10,不是20
})();

// 严格模式 会报错
var b = 10;
(function b() {
  'use strict'
  b = 20;
  console.log(b)
})() // "Uncaught TypeError: Assignment to constant variable."

// 普通函数
function a () {
    a = 1
    console.log(a)
}
a() // 1
a() // a is not a function

тридцать пять,XSSатака иCSRFатака

1,XSSатака

1. Концепция

XSS(Cross Site Scripting): Атаки с использованием междоменных сценариев.

2. Принцип

Не требует от вас какой-либо аутентификации при входе в систему, он будет проходить легальные операции (например, вurlвведите в поле для комментариев), внедрите скрипт на свою страницу (возможно,js,hmtlкодовые блоки и др.).

3. Профилактика

  1. кодирование; кодирует пользовательский ввод.
  2. Фильтрация: удаляет атрибуты, связанные с пользовательским вводом и событиями. (фильтрscript,style,iframeи т.д. узел)
  3. правильно; использоватьDOM Parseпреобразовать, исправить непарноеDOMЭтикетка.
  4. HttpOnly.

4. Классификация

  • Отражающий (непостоянный): щелкните ссылку, чтобы выполнить сценарий.
  • Хранилище (постоянное): вредоносный ввод сохраняется в базе данных, другие пользователи получают доступ, выполняют сценарии
  • на основеDOM: вредоносная модификацияDOMструктура, основанная на клиенте

2,CSRFатака

1. Концепция

SRF(Cross-site request forgery): Подделка межсайтовых запросов.

2. Принцип

  1. Войдите на надежные сайтыAи генерировать локальноCookie. (если пользователь не авторизован на сайтеA, то сайтBВо время побуждения запросите веб-сайтAизapiинтерфейс, вам будет предложено войти в систему).
  2. без выходаAВ случае посещения опасных веб-сайтовB(На самом деле, с помощью веб-сайтаAлазейки).

3. Профилактика

  1. tokenпроверять;
  2. спрятать жетон; поставитьtokenспрятаться вhttpпросилheadсередина.
  3. refererПроверка; проверяет происхождение страницы.

3. Разница между ними

  1. CSRF: требует, чтобы пользователь сначала авторизовался на веб-сайтеA,Получатьcookie.XSS: Логин не требуется.
  2. CSRF: использовать веб-сайтAУязвимость сама по себе, перейдите на сайт запросаAизapi.XSS: Да на сайтAинъекцияJSкод, затем выполнитьJSввод кода, взлом сайтаAСодержание.

Тридцать шесть,inputВход в поле ввода - это запрос внутреннего интерфейса.Как определить возвращаемое значение последнего интерфейса после частых запросов?

1. Бэкенд возвращает значение запроса (самый простой)

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

2. Завершить последний запрос

При повторном запросе последний запрос завершается:

  1. ajax:abort()
  2. axios: CancelToken
  3. fetch:AbortController

Это способ, которым Baidu отменяет запрос.

js:В любое время 1. Без редактора static.com/5en1 8AAU…

百度

3. Определите глобальныйID, интерфейс увеличивается перед запросом, а затем запрашивается закрытие интерфейса для сохранения этого значения, а после возврата выполняются два решения.

Этот метод заключается в том, чтобы не использовать серверную часть для возврата значения, а клиентская часть сохраняет соответствующую информацию о значении для обработки суждения.

выполнить

let id = 1
function ajax() {
  ++id
  console.log(id)
  function getData () {
    const newId = id
    const time = Math.random() * 5000 | 0 // 定义一个随机值
    console.log('time', time)
    setTimeout(() => {
      console.log('id newId', id, newId)
      if (id === newId) { // 在此进行数据处理
        console.log('this is true-->', id)
      }
    }, time)
  }
  getData()
}
// click 频繁点击出发函数
document.getElementById('ajaxbtn').onclick = function () {
  ajax()
}

返回结果

тридцать семь,rem

1. Определение

rem(font size of the root element)Относится к единице размера шрифта относительно корневого элемента.1remравен корневому элементуhtmизfont-size, то есть нужно установить только корневой элементfont-size, другие элементы используютremКогда единица установлена, она может быть установлена ​​на соответствующий процент.

2. Как реализовать

rem(倍数) =  width  / (html的font-size)=>  width = (html的font-size) * rem(倍数)

если толькоhtmlизfont-sizeизменился в размере,widthавтоматически изменится, поэтомуremустанавливается динамическиhtmlизfont-sizeизменитьwidthразмер для достижения цели адаптивного размера веб-страницы

Определяем формулу: rem(множественное)=ширина/(размер шрифта html), по формуле можем получить:

rem (несколько) = ширина эскиза дизайна ( imgWidth ) / размер вашего шрифта ( defalutSize ) rem (несколько) = фактическая ширина веб-страницы (ширина экрана) / размер шрифта (x), который необходимо установить динамически, тогда формула для установки размера шрифта html:

<script type="text/javascript">
  (function(w,d) {
  function setSize() {
    var screenWidth = d.documentElement.clientWidth;
    var currentFontSize = screenWidth * 100 / 750;
    d.documentElement.style.fontSize = currentFontSize + 'px';
  }
  w.addEventListener('resize',setSize);
  w.addEventListener('pageShow',setSize)
  w.addEventListener('DOMContentLoaded',setSize)
})(window,document)
</script>
function setHtmlSize(){
  var pageWidth = window.innerWidth;
  if(typeof pageWidth != "number"){ 
    if(document.compatMode == "number"){ 
      pageWidth = document.documentElement.clientWidth;
    }else{ 
      pageWidth = document.body.clientWidth; 
    } 
  } 
  var fontSize = (window.innerWidth * 100) / 750;
  if(fontSize<40){
    fontSize = 40;
  }
  //根据屏幕大小确定根节点字号
  document.getElementsByTagName('html')[0].style.fontSize = fontSize + 'px';
}
function resize(){
  setHtmlSize();
}
if (window.attachEvent) { 
  window.attachEvent("resize", resize); 
} else if (window.addEventListener) { 
  window.addEventListener("resize", resize, false);   
}
setHtmlSize();

3. С750Счетчик ширины,1rem = 100px,iphone6/7/8 plusустановить вwidth: 6.5remКакова ширина элемента?

plusСредняя ширина 414Значит ширина 414/750*6,5*100 0.32 remдля414 / 750 * 0.32 * 100

тридцать восемь,dns-prefetch,prefetch,preload,defer,async

1,dns-prefetch

доменное имя преобразовано вipэто трудоемкий процесс,dns-prefetchПозвольте браузеру сделать это за вас, когда он бездействует. Особенно большие веб-сайты будут использовать несколько доменных имен, что в настоящее время еще более необходимо.dnsПредварительная загрузка.

//来自百度首页
<link rel="dns-prefetch" href="//m.baidu.com">

2,prefetch

prefetchОбычно он используется для предварительной загрузки ресурсов, которые могут быть использованы, что, как правило, является оценкой поведения пользователя.Браузер загружает его, когда он бездействует.prefetchресурс из.

<link rel="prefetch" href="http://www.example.com/">

3.preload

а такжеprefetchразные,prefecthОбычно он загружает ресурсы страницы, которые могут быть использованы далее, иpreloadЭто скрипты, стили, шрифты, картинки и другие ресурсы, используемые для загрузки текущей страницы. такpreloadНе загружаться в режиме ожидания, он имеет более высокий приоритет и займетhttpколичество запросов.

<link rel='preload' href='style.css' as="style" onload="console.log('style loaded')"

asЗначения включают

  • script
  • style
  • image
  • media
  • document onloadМетод является функцией обратного вызова при загрузке ресурса.

4.deferа такжеasync

//defer
<script defer src="script.js"></script>
//async
<script async src="script.js"></script>

deferа такжеasyncВсе ресурсы загружаются асинхронно (параллельно), отличиеasyncвыполняется сразу после загрузки, иdeferОн не выполняется после загрузки, а будет выполняться после разбора всех элементов, т.е.DOMContentLoadedдо того, как событие сработает. потому чтоasyncЗагруженные ресурсы выполняются после загрузки, так что более чем не гарантированный порядок, в то время какdeferВыполняет скрипт по порядку.

Тридцать девять, процесс рендеринга в браузере

浏览器渲染过程

1. Процесс рендеринга в браузере выглядит следующим образом

  • РазобратьHTML, сгенерироватьDOMДерево
  • РазобратьCSS, сгенерироватьCSSOMДерево
  • БудуDOMдерево иCSSOMкомбинация деревьев для создания дерева рендеринга (Render Tree)
  • Layout(перекомпоновка): согласно сгенерированному дереву рендеринга, перекомпоновка (Layout), получить геометрическую информацию об узле (положение, размер)
  • Painting(Перерисовать): получить абсолютный пиксель узла в соответствии с геометрической информацией, полученной из дерева рендеринга и перекомпоновки.
  • Display: отправить пиксели вGPU, отображается на странице. (На самом деле есть много контента на этом этапе, напримерGPUОбъедините несколько составных слоев в один слой и отобразите его на странице. а такжеcss3Принцип аппаратного ускорения заключается в создании нового слоя синтеза)

2. Когда запускать перекомпоновку и перерисовку

1. Оплавление

  • Добавить или удалить видимыеDOMэлемент
  • Положение элемента меняется
  • Изменяются размеры элемента (включая поля, внутренние границы, размер границы, высоту и ширину и т. д.)
  • Изменения содержимого, такие как изменение текста или замена изображения другим изображением другого размера.
  • При первом отображении страницы (это определенно неизбежно)
  • Размер окна браузера изменяется (поскольку перекомпоновка вычисляет положение и размер элементов на основе размера окна просмотра)

2. Перерисовать

  • Reflow определенно вызовет перерисовку
  • Когда изменение стиля элемента на странице не влияет на его положение в потоке документов (например:color,background-color,visibilityд.), браузер назначит элементу новый стиль и перерисует его, этот процесс называется перерисовкой.

3. Если вы избегаете срабатывания перекомпоновки и перерисовки

1. css

  • избегать использованияtableмакет.
  • как можно большеDOMКонец дерева измененийclass.
  • Избегайте установки нескольких слоев встроенных стилей.
  • Применение анимационных эффектов кpositionсобственностьabsoluteилиfixedна элементе
  • избегать использованияCSSвыражения (например:calc())
  • CSS3Аппаратное ускорение(GPUускорить)
    • transform
    • opacity
    • filters
    • Will-change

2. JavaScript

  • Избегайте частых манипуляций со стилями, лучше всего переписать их все сразуstyleили определите список стилей какclassи поменять все сразуclassсвойства, изменитьstyleизcssTextатрибут или изменить элементclassNameстоимость.
  • Избегайте частых операцийDOM,СоздаватьdocumentFragment, на него распространяются всеDOMоперацию и, наконец, добавьте ее в документ
  • Вы также можете сначала установить элементdisplay: none, и отображать его после завершения операции. Потому чтоdisplayсобственностьnoneвыполняется на элементахDOMОперации не вызывают перекомпоновку и перерисовку
  • Избегайте частого чтения свойств, которые вызовут перекомпоновку/перерисовку.Если вам действительно нужно использовать их несколько раз, используйте переменную для их кэширования.
  • Используйте абсолютное позиционирование для элементов со сложной анимацией, чтобы они не попадали в поток документа, иначе это вызовет частые перекомпоновки родительских и последующих элементов.
  • использоватьcss3аппаратное ускорение, которое позволяетtransform,opacity,filtersЭти анимации не вызывают перерисовки перерисовки. Но для других свойств анимации, таких какbackground-colorОни по-прежнему будут вызывать перекомпоновку и перерисовку, но все же могут повысить производительность этих анимаций.

4. Принцип аппаратного ускорения

После того, как браузер получает документ страницы, он анализирует язык разметки в документе наDOMДерево.DOMдерево иCSSПосле комбинации браузер строит дерево рендеринга страницы. Дерево рендеринга содержит большое количество элементов рендеринга, каждый элемент рендеринга будет разделен на слой, и каждый слой будет загружен вGPUсформировать визуализированную текстуру, в то время как слойGPUсерединаtransformне сработаетrepaint, в конечном итоге они используютtransformслои обрабатываются отдельными процессами композитора.

1. Когда браузер создает отдельный составной слой?

  • 3DилиCSS transform
  • <video>а также<canvas>Этикетка
  • CSS filters
  • Когда элемент закрыт, например, при использованииz-indexАтрибуты

3Dа также2D transformРазница в том, что браузер отображает страницу для3DАнимация создает отдельный композитный слой, в то время как во время выполнения он2DСоздание анимации. Когда начинается анимация, создается и загружается новый составной слой.GPUТекстура, используемая для инициализацииrepaint. затем поGPUКомпозитор манипулирует выполнением всей анимации. Наконец, когда анимация закончится, выполните сноваrepaintДействие Удаляет составной слой.

2. Проблемы с аппаратным ускорением

  • ОЗУ. еслиGPUЗагрузка большого количества текстур может легко привести к проблемам с контентом, особенно в мобильных браузерах, поэтому не используйте аппаратное ускорение для каждого элемента страницы.
  • использоватьGPUРендеринг влияет на сглаживание шрифтов. Это потому чтоGPUа такжеCPUИмеет другой механизм рендеринга. Несмотря на то, что в конечном итоге аппаратное ускорение прекращается, текст во время анимации по-прежнему выглядит размытым.

сорок,JSBridge

1. Что такоеJSBridge

JSBridgeэтоJSосуществленныйBridge, соединяющий два конца мостаNativeа такжеH5. это вAPPУдобно впустить внутрьNativeпередачаJS,JSпередачаNative, который является каналом для двунаправленной связи.JSBridgeв основном обеспечиваетJSпередачаNativeСпособность кода реализовать нативные функции, такие как просмотр локальных альбомов, открытие камеры, оплата по отпечатку пальца и т. д.

JSBridge

2,H5а такжеnativeразница

name H5 Native
стабильность Вызов ядра системного браузера, плохая стабильность Используйте собственное ядро, более стабильное
гибкость Быстрая итерация версии, гибкий онлайн Медленная итерация, требующая проверки в магазине приложений, ограниченная скорость запуска
Влияет на скорость интернета больше меньше
Беглость Иногда загрузка идет медленно, из-за чего у пользователей возникает ощущение «заикания». Быстрая загрузка и плавность
Пользовательский опыт Функция ограничена браузером, и опыт иногда оставляет желать лучшего. родная системаapiБогатый, больше функций может быть реализовано, лучший опыт
портативность Совместимость с кросс-платформенными и кросс-системными, такими какPCс мобильным,iOSа такжеAndroid Меньшая портативность, дляiOSа такжеAndroidНеобходимо поддерживать два набора кода
### 3.JSBridgeиспользование
JSBridgeсловно "Bridge' означает то же самое,Nativeи неNativeМост между ядром которого предстоит построитьNativeи неNativeЭто канал для связи между сообщениями, и это канал для двусторонней связи.
Двусторонний канал связи:
  • JSКNativeОтправить сообщение: функции, связанные со звонком, уведомленияNativeтокJSсоответствующий статус и т. д.
  • NativeКJSОтправка сообщений: отслеживание результатов звонков, отправка сообщений, уведомленияJSтокNativeстатус и т.д.

4.JSBridgeобработать

H5-> как-то вызватьurl -> NativeЗахватитьurlАнализ -> Родной делать ->NativeпередачаH5изJSBridgeОбъект передал обратный вызов.

Процесс реализации

  • Шаг 1: СоздайтеNativeа такжеJSИнтерактивный глобальный мост
  • Шаг 2:JSКак позвонитьNative
  • третий шаг:Nativeкак знатьapiназываться
  • Шаг 4: Анализurl-Формат параметров и обратных вызовов
  • пятый шаг:NativeКак позвонитьJS
  • Шаг 6:H5серединаapiРегистрация и формат метода

5.JSBridgeПринцип реализации

  • JavaScriptпередачаNativeРекомендуется инъекцияAPIПуть(iOS6халатное отношение,Android 4.2Используйте следующееWebViewClientизonJsPromptСпособ).
  • NativeпередачаJavaScriptЗатем непосредственно выполните сваркуJavaScriptкод подойдет.

React NativeизiOSКонечный пример:JavaScriptдействующийJSCore, вы действительно можете использовать инъекцию так же, как указано вышеAPIреализоватьJavaScriptпередачаNativeФункция. ноReact Nativeне предназначен дляJavaScriptпозвонить напрямуюObject-C, но дляNativeМеханизм реагирования на события последователен в разработке, и он предназначен дляObject-CнастраиватьJavaScriptВызов инициируется только возвращаемым значением. Принцип в принципе тот же, но реализация разная.

1. NativeмелодияJS

1) Андроид

nativeпередачаjsПроще, просто следуйте: "javascript:Имя метода («параметр, необходимо преобразовать в строку»)».

mWebView.evaluateJavascript("javascript: 方法名('参数,需要转为字符串')", new ValueCallback() {
        @Override public void onReceiveValue(String value) { //这里的value即为对应JS方法的返回值 }
});
2)IOS

Nativeпройти черезstringByEvaluatingJavaScriptFromStringпередачаHtmlсвязаны вwindowфункция выше.

2. JSмелодияNative

1) Андроид

NativeпрошедшийaddJavascriptInterfaceдобавить открытыеJSобъект моста, а затем объявить соответствующийAPIметод.

private Object getJSBridge(){  
    Object insertObj = new Object(){ @JavascriptInterface public String foo(){ return "foo";  
        } @JavascriptInterface public String foo2(final String param){ return "foo2:" + param;  
        }  
    }; return insertObj;  
}
2)IOS

NativeПредставляем официальных лицJavaScriptCoreбиблиотека (iOS7выше), тоapiсвязываются сJSContextна (тогдаHtmlсерединаJSпройти по умолчаниюwindow.top.*вызываемый).

6.JSBridgeреализация интерфейса

JSBridgeСуществуют две основные функции интерфейса: передачаNative(ДатьNativeотправить сообщение) и получитьNativeпозвонить (получитьNativeИнформация).

1. Сообщения односторонние, потом звонитеNativeвремя функцииCallbackКак?

JSBridgeизCallback, по фактуRPCМеханизм обратного вызова фреймворка. Конечно прощеJSONPОписание механизма:

при отправкеJSONPпри запросе,urlпараметры будут иметьcallbackпараметр, значение которого уникально для текущей страницы, и в то же время значение этого параметраkeyсохранить функцию обратного вызова вwindow затем сервер возвращаетscript, значение параметра также будет использоваться как дескриптор, и будет вызвана соответствующая функция обратного вызова.

callbackПараметр Этот уникальный идентификатор является ключом к этой логике обратного вызова. Таким образом, мы можем обратиться к этой логике для достиженияJSBridge: использовать автоматически увеличивающийся уникальныйid, чтобы определить и сохранить функцию обратного вызова, и поместите этоidпередается в качестве параметраNative,а такжеNativeтакже таким образомidв качестве обратного идентификатора. Таким способом можно достичьCallbackлогика обратного вызова.

(function () {
    var id = 0,
        callbacks = {},
        registerFuncs = {};
    window.JSBridge = {
        // 调用 Native
        invoke: function(bridgeName, callback, data) {
            // 判断环境,获取不同的 nativeBridge
            var thisId = id ++; // 获取唯一 id
            callbacks[thisId] = callback; // 存储 Callback
            nativeBridge.postMessage({
                bridgeName: bridgeName,
                data: data || {},
                callbackId: thisId // 传到 Native 端
            });
        },
        receiveMessage: function(msg) {
            var bridgeName = msg.bridgeName,
                data = msg.data || {},
                callbackId = msg.callbackId, // Native 将 callbackId 原封不动传回
                responstId = msg.responstId;
            // 具体逻辑
            // bridgeName 和 callbackId 不会同时存在
            if (callbackId) {
                if (callbacks[callbackId]) { // 找到相应句柄
                    callbacks[callbackId](msg.data); // 执行调用
                }
            } elseif (bridgeName) {
                if (registerFuncs[bridgeName]) { // 通过 bridgeName 找到句柄
                    var ret = {},
                        flag = false;
                    registerFuncs[bridgeName].forEach(function(callback) => {
                        callback(data, function(r) {
                            flag = true;
                            ret = Object.assign(ret, r);
                        });
                    });
                    if (flag) {
                        nativeBridge.postMessage({ // 回调 Native
                            responstId: responstId,
                            ret: ret
                        });
                    }
                }
            }
        },
        register: function(bridgeName, callback) {
            if (!registerFuncs[bridgeName])  {
                registerFuncs[bridgeName] = [];
            }
            registerFuncs[bridgeName].push(callback); // 存储回调
        }
    };
})();

7.JSBridgeкак цитировать

1. поNativeинъекция

инъекционный метод иNativeпередачаJavaScriptТочно так же весь код моста выполняется напрямую.

преимущество: Мостовая версия проста в использовании сNativeЧтобы быть последовательным, нативную сторону не нужно использовать для разных версийJSBridgeсовместимый; в то же время,

недостаток: время впрыска неизвестно.Необходимо реализовать механизм повторной попытки после сбоя впрыска, чтобы обеспечить успешную скорость впрыска.JavaScriptКогда клиент вызывает интерфейс, он должен иметь приоритет.

2. ПоJavaScriptконечная ссылка

непосредственно сJavaScriptвыполнять вместе.

преимущество:JavaScriptконец можно определитьJSBridgeсуществует, вы можете вызвать его напрямую;недостаток: если есть изменения в способе реализации моста,JSBridgeСовместимость с несколькими версиямиNative BridgeилиNative BridgeСовместимость с несколькими версиямиJSBridge.

сорок один,web worker

1. Что такоеweb worker? Каковы преимущества? Какие проблемы?

Web WorkerПросто дляJavaScriptСоздайте многопоточную среду, позволяющую основному потоку создаватьWorkerПоток, который назначает выполнение некоторых задач последнему. Пока работает основной поток,WorkerПоток работает в фоновом режиме, они не мешают друг другу. Подожди покаWorkerПоток завершает задачу вычисления и возвращает результат основному потоку.

выгода:

Преимущество заключается в том, что некоторые задачи, требующие больших вычислительных ресурсов или с высокой задержкой,WorkerНить отягощена, основная нить (обычно отвечающая заUIвзаимодействие) будет плавным, не заблокированным и не замедленным.

вопрос:

WorkerКак только поток будет вновь создан, он всегда будет работать и не будет прерываться действиями в основном потоке (например, нажатие пользователем кнопки, отправка формы). Это способствует ответу на сообщение основного потока в любое время. Однако это также вызвалоWorkerОн ресурсоемкий, его нельзя использовать слишком часто, и его следует закрывать, как только он израсходован.

2. Используйтеweb workerКаковы ограничения?

1. Гомологическая рестрикция

назначен наworkerФайл сценария должен иметь тот же источник, что и файл сценария основного потока.

2. DOMограничение

workerПоток не может прочитать веб-страницу, на которой находится основной потокDOMОбъекты не могут быть использованыdocument,window,parentЭти объекты можно использоватьnavigatorа такжеlocationобъект.

3. Ограничения на общение

workerБольше не является одной и той же нитью, а основной нитью в контексте, не может напрямую связь, оно должно выполняться через сообщение.

4. Лимит скрипта

workerПоток не может быть выполненalertМетоды иconfirmметод, но может выдатьajaxпросить.

5. Ограничения файлов

workerПоток не может прочитать локальный файл, не может открыть файловую систему, загруженный скрипт должен быть из сети, а неfile://документ.

3.workerКак поток прослушивает сообщения из основного потока? Как отправляется сообщение?workerКак ветка закрывается?

WorkerВнутри потока должна быть функция слушателя для прослушиванияmessageмероприятие.

// 监听
self.addEventListener('message', function (e) {
  // 发送消息
  self.postMessage('You said: ' + e.data);
}, false);

закрытиеworkerнить

1) Основная ветка закрытаworkerнить

worker.terminate()

2)workerнить закрыть

self.close()

4.workerКак поток загружает другие скрипты?

importScript('scripts.js')
importScript('scripts1.js', 'scripts2.js')

5. Основная нить иworkerрезьбовойAPI

основной поток workerнить
Worker.onerror: уточнитьerrorфункция прослушивания событий self.name:Workerимя
Worker.onmessage: уточнитьmessageфункция прослушивания событий self.onmessage: уточнитьmessageфункция прослушивания событий
Worker.onmessageerror: уточнитьmessageerrorфункция прослушивания событий self.onmessageerror: уточнитьmessageerrorфункция прослушивания событий
Worker.postMessage()Workerнить отправить сообщение self.close(): закрытиеWorkerнить
Worker.terminate(): прекратить немедленноWorkerнить self.postMessage(): чтобы сгенерировать этоWorkerнить отправить сообщение
self.importScripts():нагрузкаJSсценарий

Сорок два,webSocket

1. Зачем нуженwebSocket? Каковы характеристики?

1. Преимущества:

  1. Поддержка двусторонней связи, более в режиме реального времени;
  2. лучшая бинарная поддержка;
  3. wsКогда клиент и сервер обмениваются данными, заголовок пакета становится меньше, а накладные расходы лучше контролируются;
  4. Поддержка расширения.

2. Особенности:

  1. УчредилTCPПомимо протокола, реализация на стороне сервера проще.
  2. а такжеHTTPПротокол имеет хорошую совместимость. Порты по умолчанию также 80 и 443, а фаза рукопожатия используетHTTPпротокол, поэтому его нелегко экранировать во время рукопожатия, и он может передавать различныеHTTPпрокси-сервер.
  3. Формат данных относительно легкий, производительность невелика, а связь эффективна.
  4. Текст может быть отправлен, или двоичные данные могут быть отправлены.
  5. Ограничений по одному и тому же источнику нет, и клиенты могут взаимодействовать с любым сервером.
  6. Идентификатор протоколаws(если зашифровано,wss), URL-адрес сервераURL.

ws

2,webSocketстатус ссылки?

  • 0 (WebSocket.CONNECTING)связывание
  • 1 (WebSocket.OPEN)Связан и доступен для общения
  • 2 (WebSocket.CLOSING)соединение закрывается
  • 3 (WebSocket.CLOSED)Соединение закрыто или ссылка не работает