[Интервью] Навыки собеседования по интерфейсу JavaScript

опрос

Заявление: МООКСоветы по собеседованию на Front-End JavaScriptЗаметки предназначены только для просмотра и обзора, а не для коммерческого использования.

BAT Дэниел проведет вас через основное интервью по интерфейсу JavaScript

Глава 1 Введение в курс

1-1 Введение в курс

Базовые знания

  • Прототип, цепь прототипов
  • размах, закрытие
  • Асинхронный, однопоточный

JS API

  • Манипуляции с DOM
  • Ajax
  • привязка события

среда разработки

  • Управление версиями
  • модульный
  • упаковочный инструмент

Рабочая среда

  • Рендеринг страницы
  • оптимизация производительности

1-2 Предисловие

Об интервью

  • Базовый инженер - Основы
  • Старший инженер - Опыт реализации проектов
  • Архитектор - Решения

На основе

  • Самосовершенствование для инженеров — основы
  • Прочная основа позволит вам эффективно изучать новые технологии

1-3 Несколько вопросов интервью

Начнем с нескольких вопросов интервью

  • используется в JStypeof Какие типы доступны?
  • когда использовать===, когда использовать==?
  • window.onloadа такжеDOMContentLoadedразница?
  • Создайте 10 с помощью JS<a>Метка, при нажатии на которую появится соответствующий серийный номер
  • Кратко опишите, как реализовать загрузчик модулей, который реализует что-то вродеrequire.jsосновные функции
  • Реализовать случайную сортировку массивов

думать

  • Когда вам задают вопрос на собеседовании, что вы видите в первую очередь?
  • Как вы смотрите на бескрайнее море вопросов, найденных в Интернете?
  • Как ответить на следующие вопросы интервью?

1-4 Как получить все вопросы интервью

Заключение предыдущего раздела размышления о проблеме

  • Когда вам задают вопрос на собеседовании, что вы видите в первую очередь? -испытательный центр
  • Как вы смотрите на бескрайнее море вопросов, найденных в Интернете? -изменить без изменений
  • Как ответить на следующие вопросы интервью? -тема к знаниям к теме

Очки знаний по теме исследования

  • используется в JStypeofКакие типы доступны? Тестовый сайт:Тип переменной JS
  • когда использовать===, когда использовать==? Тестовый сайт:принуждение
  • window.onloadа такжеDOMContentLoadedразница? Тестовый сайт:процесс рендеринга в браузере
  • Создайте 10 с помощью JS<a>Метка, при нажатии на которую появится соответствующий серийный номер Тестовый сайт:объем
  • Кратко опишите, как реализовать загрузчик модулей, который реализует что-то вродеrequire.jsосновные функции Тестовый сайт:Модульный JS
  • Реализовать случайную сортировку массивов Тестовый сайт:Базовый алгоритм JS

Глава 2. Основы JS (Часть 1)

2-1 Типы переменных и вычисления - 1

тема

  • используется в JStypeofКакие типы доступны?
  • когда использовать===, когда использовать==?
  • Какие есть встроенные функции в JS?
  • Каковы типы переменных JS в соответствии с их методами хранения и описанием их характеристик?
  • Как понять JSON?

Точка знаний

  • тип переменной
  • Расчет переменных

тип переменной

  • тип значения, ссылочный тип
  • typeofоператор

тип значения

let a = 100
let b = a
a = 200
console.log(b) // 100

тип ссылки

let a = { age: 20 }
let b = a
b.age = 21
console.log(a.age) // 21

typeofоператор

typeof undefined // "undefined"
typeof 'abc' // "string"
typeof 123 // "number"
typeof true // "boolean"
typeof {} // "object"
typeof [] // "object"
typeof null // "object"
typeof console.log // "function"

Переменная оценка - принуждение

Конкатенация строк

let a = 100 + 10 // 110
let b = 100 + '10' // "10010"

==оператор

100 == '100' // true
0 == '' // true
null = undefined // true

ifутверждение

let a = true
if (a) {}
let b = 100
if (b) {}
let c = ''
if (c) {}

Логические операторы

console.log(10 && 0) // 0
console.log('' || 'abc') // "abc"
console.log(!window.abc) // true

// 判断一个变量会被当做 true 还是 false
let a = 100
console.log(!!a) // true

2-2 Типы переменных и вычисления - 2

отвечать

используется в JStypeofКакие типы доступны?

отвечать:undefined,string,number,boolean,object,function,symbol

let sym = Symbol('commet')
console.log(typeof sym) // "symbol"

когда использовать===, когда использовать==?

Ответ: Определить, существует ли свойство объекта.nullможно использовать, когда==, так как исходный код jQuery использует

if (obj.a == null) {
  // 这里相当于 obj.a === null || obj.a === undefined 的简写形式
  // 这是 jQuery 源码中推荐的写法
}

Какие есть встроенные функции в JS?

Ответ: Объекты класса инкапсуляции данных, включаяString,Number,Boolean,Object,Array,Function,Date,RegExp,Error

Каковы типы переменных JS в соответствии с их методами хранения и описанием их характеристик?

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

2-3 Типы переменных и вычисления - 3

Как понять JSON?

Ответ: JSON — это просто объект JS и формат данных.

JSON.stringify({ a: 10, b: 20 })
JSON.parse('{"a":10,"b":20}')

2-4 Типы переменных и расчеты — демонстрация кода

ifВ заявлении есть условиеfalseЧто за ситуация?

отвечать:'',0,NaN,false,null,undefined

Что такое встроенные объекты в JS?

отвечать:JSON,Math

2-5 typeof symbol

let s = Symbol()
typeof s // "symbol"
let s1 = Symbol()
console.log(s === s1) // false
let s2 = Symbol('s2s2')
console.log(s2) // Symbol(s2s2)
let s3 = s2
console.log(s3 === s2) // true
let sym1 = Symbol('111')
let sym2 = Symbol('222')
let obj = { [sym1]: 'hello world' }
obj[sym2] = 123
console.log(obj) // {Symbol(111): "hello world", Symbol(222): 123}
console.log(obj[sym1]) // "hello world"
console.log(obj[sym2]) // 123

2-6 прототипов и цепочек прототипов

тема

  • Как точно определить, является ли переменная типом массива
  • Напишите пример наследования цепочки прототипов
  • описыватьnewпроцесс объекта
  • Как использовать цепочку прототипов в zepto или другом исходном коде фреймворка

Точка знаний

  • Конструктор
  • Конструктор - Расширение
  • Правила и примеры прототипов
  • Сеть прототипов
  • instanceof

Конструктор

function Foo(name, age) {
  this.name = name
  this.age = age
  this.class = 'class__1'
  // return this // 默认有这一行
}
let f = new Foo('negrochn', 18)
// let f2 = new Foo('lexiaodai', 17) // 创建多个对象

Конструктор - Расширение

let a = {} // 其实是 let a = new Object() 的语法糖
let b = [] // 其实是 let b = new Array() 的语法糖
function Foo() {} // 其实是 let Foo = new Function()
// 使用 instanceof 判断一个函数是否是一个变量的构造函数
console.log(b instanceof Array) // true

2-7 Прототипы и цепочки прототипов - 5 правил прототипов

5 правил прототипа

  1. Все ссылочные типы (массивы, объекты, функции) имеют объектные свойства, которые можно свободно расширять (кромеnullза пределами)
  2. Все ссылочные типы (массивы, объекты, функции) имеют__proto__(Неявный прототип), значением свойства является простой объект
  3. Все функции имеютprototype(Явный прототип), значение свойства также является обычным объектом
  4. все ссылочные типы (массивы, объекты, функции),__proto__Значение свойства указывает на его конструкторprototypeзначение атрибута
  5. При попытке получить атрибут объекта, если сам объект не имеет этого атрибута, он перейдет к своему__proto__(т.е. его конструкторprototype) найти
// 原则 1
let obj = {}
obj.a = 100
let arr = []
arr.a = 100
function fn() {}
fn.a = 100

// 原则 2
console.log(obj.__proto__)
console.log(arr.__proto__)
console.log(fn.__proto__)

// 原则 3
console.log(fn.prototype)

// 原则 4
console.log(obj.__proto__ === Object.prototype) // true
// 构造函数
function Foo(name) {
  this.name = name
}
Foo.prototype.alertName = function() {
  alert(this.name)
}

// 创建实例
let f = new Foo('negrochn')
f.printName = function() {
  console.log(this.name)
}
// 测试
f.printName()
f.alertName() // 原则 5

2-8 прототипов и цепочек прототипов - добавлено 5 правил для прототипов 2 очка

for (let key in f) {
  // 高级浏览器已经在 for in 中屏蔽了来自原型的属性
  // 但是这里建议大家还是加上这个判断,保证程序的健壮性
  if (f.hasOwnProperty(key)) {
    console.log(key)
  }
}

2-9 Прототипы и цепочки прототипов - Цепочки прототипов

// 构造函数
function Foo(name) {
  this.name = name
}
Foo.prototype.alertName = function() {
  alert(this.name)
}

// 创建实例
let f = new Foo('negrochn')
f.printName = function() {
  console.log(this.name)
}
// 测试
f.printName()
f.alertName()
f.toString() // 要去 f.__proto__.__proto__ 中查找

原型链

2-10 прототипов и цепочек прототипов — instanceof

// instanceof 用于判断引用类型属于哪个构造函数的方法
console.log(f instanceof Foo) // true, f 的 __proto__ 一层一层往上,能否对应到 Foo.prototype
console.log(f instanceof Object) // true

2-11 Прототипы и цепочки прототипов — Решение 1

Как точно определить, является ли переменная типом массива

Ответ: использоватьinstanceof Array

let arr = []
console.log(arr instanceof Array) // true
console.log(typeof arr) // "object" ,typeof 是无法判断是否是数组的

Напишите пример наследования цепочки прототипов

// 动物
function Animal() {
  this.eat = function() {
    console.log('animal eat')
  }
}
// 狗
function Dog() {
  this.bark = function() {
    console.log('dog bark')
  }
}
Dog.prototype = new Animal()
// 哈士奇
let hashiqi = new Dog()

// 接下来代码演示时,会推荐更加贴近实战的原型继承示例

описыватьnewпроцесс объекта

отвечать:

  1. создать новый объект
  2. thisуказывает на этот новый объект
  3. выполнить код, т.е.thisназначать
  4. вернутьthis
function Foo(name, age) {
  this.name = name
  this.age = age
  this.class = 'class__1'
  // return this // 默认有这一行
}

let f = new Foo('negrochn', 18)

Как использовать цепочку прототипов в zepto или другом исходном коде фреймворка

отвечать:

  • Чтение исходного кода — эффективный способ улучшить свои навыки
  • Но сильно "просверлить голову" нельзя, в этом есть навыки
  • Поиск МООК "дизайн zepto и анализ исходного кода"

2-12 Прототипы и цепочки прототипов — Решение 2

Напишите пример, который инкапсулирует запрос DOM

function Elem(id) {
  this.elem = document.getElementById(id)
}

Elem.prototype.html = function(val) {
  let elem = this.elem
  if (val) {
    elem.innerHTML = val
    return this // 为了链式操作
  } else {
    return elem.innerHTML
  }
}

Elem.prototype.on = function(type, fn) {
  let elem = this.elem
  elem.addEventListener(type, fn)
  return this // 为了链式操作
}

let div1 = new Elem('div1')
div1.html('<p>Hello World</p>').on('click', function() {
  alert('clicked')
})

2-13 Прототипы и цепочки прототипов — Демонстрация кода

без

Глава 3. Основы JS (Часть 2)

3-1 Область действия и замыкания — контекст выполнения

тема

  • Поговорите о понимании переменного продвижения
  • иллюстрироватьthisНесколько разных сценариев использования
  • Создать 10<a>Метка, при нажатии на которую появится соответствующий серийный номер
  • Как понять охват
  • Применение замыканий в реальной разработке

Точка знаний

  • контекст выполнения
  • this
  • объем
  • цепочка прицелов
  • Закрытие

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

  • Объем: один сегмент<script>или функция
  • Глобальный контекст: перед выполнением будут удалены определения переменных и объявления функций (обратите внимание на разницу между объявлениями функций и функциональными выражениями).
  • Контекст функции: перед выполнением поместите определения переменных, объявления функций,this,argumentsвозьми это
console.log(a) // undefined
var a = 100

fn('negrochn') // "negrochn" 20
function fn(name) {
  age = 20
  console.log(name, age)
  var age
}

3-2 Scope и Closures — Демонстрация кода контекста выполнения

без

3-3 Scope и Closures - это

this, значение может быть подтверждено только во время выполнения и не может быть подтверждено во время определения

  • Выполнить как конструктор
  • Выполнить как свойство объекта
  • Выполнить как обычную функцию
  • call,apply,bind
var a = {
  name: 'A',
  fn: function() {
    console.log(this.name)
  }
}
a.fn() // this === a
a.fn.call({ name: 'B' }) // this 作为 { name: 'B' }
var fn1 = a.fn
fn1() // this === window

3-4 Scope and Closures — эта демонстрация кода

// 作为构造函数执行
function Foo(name) {
  this.name = name
}
let f = new Foo('negrochn')
f.name // "negrochn"
// 作为对象属性执行
let obj = {
  name: 'A',
  printName: function() {
    console.log(this.name)
  }
}
obj.printName() // "A"
// 作为普通函数执行
function fn() {
  console.log(this)
}
fn() // window
// call 、apply 、bind
function fn1(name, age) {
  console.log(name)
  console.log(this)
}
fn1.call({ x: 1 }, 'negrochn', 20) // "negrochn" { x: 1 }
fn1.apply({ x: 200 }, ['negrochn', 20]) // "negrochn" { x: 200 }

let fn2 = function(name, age) {
  console.log(name)
  console.log(this)
}.bind({ x: 300 })
fn2('negrochn', 20) // "negrochn" { x: 300 }

3-5 Область действия и замыкания - Область действия

объем

  • нет области блока
  • Только функции и глобальный объем
// 无块级作用域
if (true) {
  var name = 'negrochn'
}
console.log(name) // "negrochn"

// 只有函数和全局作用域
var a = 100
function fn() {
  var a = 200
  console.log('fn', a)
}
console.log('global', a) // "global" 100
fn() // "fn" 200

цепочка прицелов

var a = 100
function fn() {
  var b = 200
  // 当前作用域没有定义的变量,即“自由变量”
  console.log(a)
  console.log(b)
}
fn()
var a = 100
function f1() {
  var b = 200
  function f2() {
    var c = 300
    console.log(a) // a 是自由变量
    console.log(b) // b 是自由变量
    console.log(c)
  }
  f2()
}
f1()

3-6 Scope and Closures — Демонстрация кода Scope

без

3-7 Дополнение - Объем блока ES6

JS не имеет блочной области, ES6 имеет блочную область

3-8 Область действия и замыкания — замыкания

Закрытие

function f1() {
  var a = 100
  // 返回一个函数(函数作为返回值)
  return function() {
    console.log(a)
  }
}
// f1 得到一个函数
var f = f1()
var a = 200
f() // 100

Сценарии использования закрытия

  • функция как возвращаемое значение
  • функция передана как параметр

3-9 Scope and Closures — Демонстрация кода замыкания

// 闭包 1 ,函数作为返回值
function f1() {
  var a = 100
  return function() {
    console.log(a) // a 是自由变量,向父级作用域去寻找,函数定义时的父作用域
  }
}
var f = f1()
var a = 200
f() // 100
// 闭包 2 ,函数作为参数传递
function f1() {
  var a = 100
  return function() {
    console.log(a)
  }
}
var f = f1()
function f2(fn) {
  var a = 200
  fn()
}
f2(f) // 100

3-10 Область действия и замыкания — решение проблем

Поговорите о понимании переменного продвижения

  • Определения переменных
  • Объявление функции (обратите внимание на отличие от функциональных выражений)

иллюстрироватьthisНесколько разных сценариев использования

  • Выполнить как конструктор
  • Выполнить как свойство объекта
  • Выполнить как обычную функцию
  • call,apply,bind

Создать 10<a>Метка, при нажатии на которую появится соответствующий серийный номер

// 这是一个错误的写法
var i, a
for(i = 0; i < 10; i++) {
  a = document.createElement('a')
  a.innerHTML = i + '<br>'
  a.addEventListener('click', function(e) {
    e.preventDefault()
    alert(i) // 自由变量,要去父作用域获取值
  })
  document.body.appendChild(a)
}
// 这是正确的写法
var i
for(i = 0; i < 10; i++) {
  (function(i) {
    var a = document.createElement('a')
    a.innerHTML = i + '<br>'
    a.addEventListener('click', function(e) {
      e.preventDefault()
      alert(i)
    })
    document.body.appendChild(a)
  })(i)
}

Если вы понимаете масштаб

  • свободная переменная
  • Цепочка областей видимости, т. е. поиск свободных переменных
  • Два сценария закрытия

Применение замыканий в реальной разработке

// 闭包实际应用中主要用于封装变量,收敛权限
function isFirstLoad() {
  var _list = []
  return function(id) {
    if (_list.indexOf(id) >= 0) {
      return false
    } else {
      _list.push(id)
      return true
    }
  }
}

// 使用
var firstLoad = isFirstLoad()
console.log(firstLoad(10)) // true
console.log(firstLoad(10)) // false
console.log(firstLoad(20)) // true
// 你在 isFirstLoad 函数外,根本不可能修改掉 _list 的值

3-11 Scope and Closures — Демонстрация кода решения проблем

без

Глава 4. Основы JS (Часть 2)

4-1 Асинхронный и однопоточный — что такое асинхронный

тема

  • В чем разница между синхронным и асинхронным? Приведите пример синхронного и асинхронного соответственно
  • Письменный тестовый вопрос о setTimeout
  • Каковы сценарии, в которых внешний интерфейс использует асинхронность?

Точка знаний

  • Что такое асинхронный (по сравнению с синхронным)
  • Внешний интерфейс с использованием асинхронных сценариев
  • Асинхронный и однопоточный

что такое асинхронный

  • Блокировать последующее выполнение кода синхронно
  • Асинхронный не блокирует выполнение программы
console.log(100)
setTimeout(function() {
  console.log(200)
}, 1000)
console.log(300)

Контрастная синхронизация

console.log(100)
alert(200) // 1 秒之后手动点击确认
console.log(300)

Когда вам нужен асинхронный

  • в случае ожидания
  • не может быть как в ожиданииalertта самая блокирующая программа
  • Следовательно, все «ожидающие случаи» должны быть асинхронными.

Внешний интерфейс с использованием асинхронных сценариев

  • задания на время,setTimeout,setInterval
  • Сетевой запрос, запрос Ajax, динамический<img>нагрузка
  • привязка события
// Ajax 请求
console.log('start')
$.get('./data1.json', function(data1) {
  console.log(data1)
})
console.log('end')
// 动态 <img> 加载
console.log('start')
var img = document.createElement('img')
img.onload = function() {
  console.log('loaded')
}
img.src = '/xxx.png'
console.log('end')
// 事件绑定
console.log('start')
document.getElementById('btn1').addEventListener('click', function() {
  alert('clicked')
})
console.log('end')

4-2 Асинхронный и однопоточный — что такое асинхронный код Демонстрация

без

4-3 Асинхронный и однопоточный — однопоточный

console.log(100)
setTimeout(function() {
  console.log(200)
})
console.log(300)
  1. выполнить строку 1, вывести 100
  2. воплощать в жизньsetTimeoutПосле этого пройти вsetTimeoutФункция будет временно сохранена и не будет выполняться немедленно (однопоточная функция, не может делать две вещи одновременно)
  3. выполнить строку 5, вывести 300
  4. После того, как все программы будут выполнены и находятся в состоянии ожидания, они сразу же увидят, есть ли что-то временно сохраненное для выполнения.
  5. Если вы найдете функцию во временно сохраненном setTimeout, вы можете выполнить ее немедленно, не дожидаясь времени.

один поток

  • JS — это однопоточный язык, то есть вы можете делать только одно дело за раз, если есть два дела одновременно, то другое будет стоять в очереди первым, я закончу это дело первым, если нет асинхронный, будет блокировка.
  • Поскольку JS — это один поток, его нельзя заблокировать из-за выполнения кода, которому нужно ждать во время выполнения кода, поэтому JS сначала выполнит (синхронный) код, которому не нужно ждать, а затем обработает асинхронный код. Если выполнение асинхронного кода достигнуто условие, он будет выполнен

4-4 Асинхронный и однопоточный — ответы

В чем разница между синхронным и асинхронным? Приведите пример синхронного и асинхронного соответственно

  • Синхронный блокирует выполнение кода, а асинхронный нет.
  • alertсинхронный,setTimeoutасинхронный

Письменный тестовый вопрос о setTimeout

console.log(1)
setTimeout(function() {
  console.log(2)
}, 0)
console.log(3)
setTimeout(function() {
  console.log(4)
}, 1000)
console.log(5)
// 1
// 3
// 5
// 2
// 4 ,一秒后

Каковы сценарии, в которых внешний интерфейс использует асинхронность?

  • задания на время,setTimeout,setInterval
  • Сетевой запрос, запрос Ajax, динамический<img>нагрузка
  • привязка события

Основные моменты

  • разница между асинхронным и синхронным
  • Асинхронные и однопоточные отношения
  • Сценарии асинхронного использования во внешнем интерфейсе

4-5 Другие точки знаний - дата и математика

тема

  • Получать2020-02-24дата в формате
  • Получить случайное число, требующее строкового формата той же длины
  • Напишите дженерик, который перебирает объекты и массивы.forEachфункция

Точка знаний

  • Date
  • Math
  • API-интерфейс массива
  • API объекта

Date

Date.now() // 获取当前时间毫秒数
var dt = new Date()
dt.getTime() // 获取毫秒数
dt.getFullYear() // 年
dt.getMonth() // 月(0-11)
dt.getDate() // 日(1-31)
dt.getHours() // 时(0-23)
dt.getMinutes() // 分(0-59)
dt.getSeconds() // 秒(0-59)

Math

Math.random() // 获取随机数

4-6 Другие точки знаний - API массивов и объектов

API-интерфейс массива

  • forEach, перебирает все элементы
  • every, чтобы определить, все ли элементы удовлетворяют условиям
  • some, чтобы определить, удовлетворяет ли хотя бы один элемент условию
  • sort, Сортировать
  • map, который собирает элементы для создания нового массива
  • filter, фильтровать элементы, соответствующие условию
// forEach
var arr = [1, 2, 3]
arr.forEach(function(item, index) {
  // 遍历数组的所有元素
  console.log(index, item)
})
// 0 1
// 1 2
// 2 3
// every
var arr = [1, 2, 3]
var result = arr.every(function(item, index) {
  // 用来判断所有的数组元素,都满足条件
  if (item < 4) {
    return true
  }
})
console.log(result) // true
// some
var arr = [1, 2, 3]
var result = arr.some(function(item, index) {
  // 用来判断只要有一个数组元素满足条件
  if (item < 2) {
    return true
  }
})
console.log(result) // true
// sort
var arr = [1, 4, 2, 3, 5]
var result = arr.sort(function(a, b) {
  // 从小到大排序
  return a - b // 从大到小排序 return b - a
})
console.log(result) // [1, 2, 3, 4, 5]
// map
var arr = [1, 2, 3]
var result = arr.map(function(item, index) {
  // 将元素重新组装并返回
  return '<b>' + item + '</b>'
})
console.log(result) //  ["<b>1</b>", "<b>2</b>", "<b>3</b>"]
// filter
var arr = [1, 2, 3]
var result = arr.filter(function(item, index) {
  // 通过某一个条件过滤数组
  if (item >= 2) {
    return true
  }
})
console.log(result) // [2, 3]

API объекта

var obj = {
  x: 100,
  y: 200,
  z: 300
}
var key
for (key in obj) {
  // 注意这里的 hasOwnProperty ,在将原型链的时候讲过了
  if (obj.hasOwnProperty(key)) {
    console.log(key, obj[key])
  }
}
// x 100
// y 200
// z 300

4-7 Другие точки знаний — Демонстрация кода точек знаний

без

4-8 Другие точки знаний - ответы

Получать2020-02-24дата в формате

function formatDate(dt) {
  if (!dt) {
    dt = new Date()
  }
  var year = dt.getFullYear()
  var month = dt.getMonth() + 1
  var date = dt.getDate()
  return year + '-' + month.toString().padStart(2, '0') + '-' + date.toString().padStart(2, '0')
}

formatDate(new Date()) // "2021-02-24"

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

var random = Math.random()
random = random + '0000000000'
random = random.slice(0, 10)
console.log(random)

Напишите дженерик, который перебирает объекты и массивы.forEachфункция

function forEach(obj, fn) {
  var key
  if (obj instanceof Array) {
    obj.forEach(function(item, index) {
      fn(index, item)
    })
  } else {
    for (key in obj) {
      fn(key, obj[key])
    }
  }
}

var arr = [1, 2, 3]
forEach(arr, function(key, value) {
  console.log(key, value)
})
// 0 1
// 1 2
// 2 3

var obj = {
  x: 100,
  y: 200
}
forEach(obj, function(key, value) {
  console.log(key, value)
})
// x 100
// y 200

Основные моменты

  • Date
  • Math
  • API-интерфейс массива
  • API объекта

4-9 Другие точки знаний — Демонстрация кода

Глава 5 Веб-API JS (часть 1)

5-1 От основ к JS Web API

Ознакомьтесь с основами JS

  • Типы переменных и вычисления
  • Прототипы и цепочки прототипов
  • Закрытие и объем
  • Асинхронный и однопоточный
  • Другие (такие как Date , Math , различные распространенные API)
  • Особенности: на первый взгляд кажется, что он не используется для разработки кода на работе.
  • Встроенные функции: объект, массив, логический, строка ...
  • Встроенный объект: Math, JSON...
  • Мы даже всплываем предложение на веб-страницеHello Worldне может быть достигнуто

JS Web API

  • Основы JS: стандарт ECMA262
  • Веб-API JS: стандарт W3C

Положения о JS в стандарте W3C:

  • Манипуляции с DOM
  • Операции со спецификациями
  • привязка события
  • Ajax-запросы (включая протокол http)
  • место хранения

Всплывающее окно страницыwindow.alert(123), браузер должен сделать

  • определитьwindowглобальная переменная, тип объекта
  • определить егоalertсвойство, значение свойства является функцией

получить элементdocument.getElementById(id), браузер требует

  • определитьdocumentглобальная переменная, тип объекта
  • Определить это А.getElementByIdсвойство, значение свойства является функцией

Но стандарт W3C ничего не говорит об основах JS.

  • Независимо от типа переменной, прототипа, области действия и асинхронности
  • Просто определите API и глобальные переменные для страниц манипулирования JS в браузере.

Всестороннее рассмотрение, что такое встроенные глобальные функции и объекты в JS?

  • Объект, массив, логическое значение, строка, математика, JSON и т. д.
  • только что упомянутое окно, документ
  • Затем идут все неопределенные глобальные переменные, которые продолжают упоминаться, напримерnavigator.userAgent

Суммировать

Часто говорят, что JS (Browser Executed JS) состоит из двух частей.

  • Основы JS (стандарт ECMA262)
  • Веб-API JS (стандарт W3C)

5-2 суть ДОМ

DOM, полное название Объектная модель документа

тема

  • Какой базовой структурой данных является DOM?
  • Каковы общие API для манипулирования DOM?
  • В чем разница между атрибутом и свойством узла DOM?

Точка знаний

  • суть ДОМ
  • Управление узлами DOM
  • Структура DOM операции

суть ДОМ

<?xml version="1.0" encoding="utf-8"?>
<note>
  <to>Tove</to>
  <from>Jani</from>
  <heading>Reminder</heading>
  <body>Don't forget me this weekend</body>
  <other>
    <a></a>
    <b></b>
  </other>
</note>
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <div>
    <p>this is p</p>
  </div>
</body>
</html>

Суть DOM: после того, как браузер получает HTML-код, DOM структурирует HTML-код во что-то, что может распознать браузер и JS.

HTML-код — это просто строка, но браузер уже структурировал строку в древовидную структуру.

5-3 Операции с DOM-узлом

DOM можно понимать так: браузер структурирует HTML-код, который он получает, в модель, которую браузер может распознать и которой может манипулировать JS.

Управление узлами DOM

  • Получить узел DOM
  • Свойство, свойство объекта JS
  • Атрибут , атрибут HTML-тега

Получить узел DOM

var div1 = document.getElementById('div1') // 元素
var divList = document.getElementsByTagName('div') // 集合
console.log(divList.length)
console.log(divList[0])

var containerList = document.getElementsByClassName('container') // 集合
var pList = document.querySelectorAll('p') // 集合

Свойство, свойство объекта JS

var pList = document.querySelectorAll('p')
var p = pList[0]
console.log(p.style.width) // 获取样式
p.style.width = '100px' // 修改样式
console.log(p.className) // 获取 class
p.className = 'p1' // 修改 class

// 获取 nodeName 和 nodeType
console.log(p.nodeName) // "P"
console.log(p.nodeType) // 1

Атрибут , атрибут HTML-тега

var pList = document.querySelectorAll('p')
var p = pList[0]
p.getAttribute('data-name')
p.setAttribute('data-name', 'imooc')
p.getAttribute('style')
p.setAttribute('style', 'font-size: 30px;')

5-4 Работа с узлом DOM — демонстрация кода

без

5-5 Управление структурой DOM

Управление структурой DOM

  • новый узел
  • получить родительский элемент
  • получить дочерний элемент
  • удалить узел

новый узел

var div1 = document.getElementById('div1')
// 添加新节点
var p = document.createElement('p')
p.innerHTML = 'new p'
div1.appendChild(p) // 添加新创建的元素
// 移动已有节点
var p4 = document.getElementById('p4')
div1.appendChild(p4)

Получить родительские и дочерние элементы

var div1 = document.getElementById('div1')
var parent = div1.parentNode

var children = div1.childNodes

удалить узел

div1.removeChild(children[0])

5-6 Управление структурой DOM — демонстрация кода

без

5-7 Управление структурой DOM — ответы

Какой базовой структурой данных является DOM?

Ответ: дерево

Каковы общие API для манипулирования DOM?

отвечать:

  • Получите узел DOM, а также свойство и атрибут узла
  • получить родительский узел, получить дочерний узел
  • добавить узел, удалить узел

В чем разница между атрибутом и свойством узла DOM?

отвечать:

  • Свойство — это просто модификация свойств объекта JS.
  • Атрибут — это модификация атрибутов тега HTML.

Основные моменты

  • суть ДОМ
  • Управление узлами DOM
  • Управление структурой DOM

5-8 Операция со спецификацией

тема

  • Как определить тип браузера
  • Разбить части URL

Точка знаний

  • navigator
  • srceen
  • location
  • history

navigator & screen

// navigator
var ua = navigator.userAgent
var isChrome = ua.indexOf('Chrome')
console.log(isChrome) // 81

// screen
console.log(screen.width) // 1920
console.log(screen.height) // 1080

location & history

// location ,以 http://localhost:8080/login?username=negrochn&password=123456#mid=1 为例
console.log(location.href) // http://localhost:8080/login?username=negrochn&password=123456#mid=1
console.log(location.protocol) // http:
console.log(location.host) // localhost:8080
console.log(location.hostname) // localhost
console.log(location.port) // 8080
console.log(location.pathname) // /login
console.log(location.search) // ?username=negrochn&password=123456
console.log(location.hash) // #mid=1

// history
history.back()
history.forward()

5-9 Работа со спецификацией — демонстрация кода

без

Глава 6 Веб-API JS (часть 2)

6-1 События

тема

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

Точка знаний

  • Общая привязка событий
  • всплывающее окно событий
  • играет роль

Общая привязка событий

var btn = document.getElementById('btn1')
btn.addEventListener('click', function(e) {
  console.log('clicked')
})

function bindEvent(elem, type, fn) {
  elem.addEventListener(type, fn)
}
var a = document.getElementById('link1')
bindEvent(a, 'click', function(e) {
  e.preventDefault() // 阻止默认行为
  alert('clicked')
})

Совместимость с более ранними версиями IE

  • Использование более низкой версии IEattachEventСобытия привязки, не такие, как в стандарте W3C
  • Использование более ранней версии IE было очень небольшим, и многие веб-сайты больше не поддерживают ее.
  • Рекомендуется совместимость с младшими версиями IE: просто разберитесь, не нужно вникать
  • Если вы встретите требовательное интервью с более низкой версией IE, решительно сдавайтесь.

всплывающее окно событий

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>事件冒泡</title>
</head>
<body>
  <div id="div1">
    <p id="p1">激活</p>
    <p id="p2">取消</p>
    <p id="p3">取消</p>
    <p id="p4">取消</p>
  </div>
  <div id="div2">
    <p id="p5">取消</p>
    <p id="p6">取消</p>
  </div>
  <script>
    function bindEvent(elem, type, fn) {
      elem.addEventListener(type, fn)
    }
    
    var p1 = document.getElementById('p1')
    var body = document.body
    bindEvent(p1, 'click', function(e) {
      e.stopPropagation()
      alert('激活')
    })
    bindEvent(body, 'click', function(e) {
      alert('取消')
    })
  </script>
</body>
</html>

играет роль

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>事件冒泡</title>
</head>
<body>
  <div id="div1">
    <a href="#">a1</a>
    <a href="#">a2</a>
    <a href="#">a3</a>
    <a href="#">a4</a>
    <!-- 会随时新增更多 a 标签 -->
  </div>
  <script>
    var div1 = document.getElementById('div1')
    div1.addEventListener('click', function(e) {
      var target = e.target
      if (target.nodeName === 'A') {
        alert(target.innerHTML)
      }
    })
  </script>
</body>
</html>

Улучшить функцию общего события привязки

function bindEvent(elem, type, selector, fn) {
  if (fn == null) {
    fn = selector
    selector = null
  }
  elem.addEventListener(type, function(e) {
    var target
    if (selector) {
      target = e.target
      if (target.matches(selector)) {
        fn.call(target, e)
      }
    } else {
      fn(e)
    }
  })
}

// 使用代理
var div1 = document.getElementById('div1')
bindEvent(div1, 'click', 'a', function(e) {
  console.log(this.innerHTML)
})

// 不使用代理
var a = document.getElementById('a1')
bindEvent(div1, 'click', function(e) {
  console.log(a.innerHTML)
})

Преимущества прокси

  • код краткий
  • Уменьшите использование памяти браузера

6-2 События — Демонстрация кода

без

6-3 События - Ответы

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

отвечать:

function bindEvent(elem, type, selector, fn) {
  if (fn == null) {
    fn = selector
    selector = null
  }
  elem.addEventListener(type, function(e) {
    let target
    if (selector) {
      target = e.target
      if (target.matches(selector)) {
        fn.call(target, e)
      }
    } else {
      fn(e)
    }
  })
}

Описать процесс всплытия событий

отвечать:

  1. Древовидная структура DOM
  2. всплывающее окно событий
  3. перестань пузыриться
  4. всплывающее приложение

Как привязать событие к каждому изображению на странице, которая загружает изображения в бесконечном раскрывающемся списке

отвечать:

  • использовать прокси
  • Два преимущества прокси (краткий код, уменьшение использования памяти браузером)

Основные моменты

  • Общая привязка событий
  • всплывающее окно событий
  • агент событий

6-4 Ajax - XMLHttpRequest

тема

  • Напишите Ajax, не полагаясь на сторонние библиотеки
  • Несколько реализаций междоменного

Точка знаний

  • XMLHttpRequest
  • Описание кода состояния
  • перекрестный домен

XMLHttpRequest

var xhr = new XMLHttpRequest()
xhr.open('GET', '/api', false)
xhr.onreadystatechange = function() {
  // 这里的函数异步执行
  if (xhr.readyState == 4) {
    if (xhr.status == 200) {
      alert(xhr.responseText)
    }
  }
}
xhr.send(null)

Проблемы совместимости с IE

  • Младшая версия IE использует ActiveXObject, что не совпадает со стандартом W3C.
  • Использование более ранней версии IE было очень небольшим, и многие веб-сайты больше не поддерживают ее.
  • Рекомендуется совместимость с младшими версиями IE: просто разберитесь, не нужно вникать
  • Если вы встретите требовательное интервью с более низкой версией IE, решительно сдавайтесь.

readyState

  • 0 - не инициализирован, метод send() не вызывался
  • 1 - Загрузка, вызывается метод send(), запрос отправляется
  • 2 - Загрузка завершена, метод send() выполнен, и все содержимое ответа получено
  • 3 - Интерактивный, анализирующий содержимое ответа
  • 4 - Готово, содержимое ответа анализируется и может быть вызвано на стороне клиента

status

  • 1XX - Информация, сервер получил запрос и запрашивающей стороне необходимо продолжить операцию
  • 2XX - Успех, операция успешно получена и обработана
  • 3XX — перенаправление, для выполнения запроса требуются дальнейшие действия.
  • 4XX - Ошибка клиента, запрос содержит синтаксическую ошибку или запрос не может быть выполнен
  • 5XX — Ошибка сервера, сервер обнаружил ошибку при обработке запроса
код состояния английское описание Китайское описание
100 Continue Продолжать. Клиент должен продолжить выполнение своего запроса.
200 OK Запрос выполнен успешно.
204 No Content Без содержания. Сервер успешно обработал, но не вернул содержимого.
206 Partial Content Часть. Сервер успешно обработал часть запроса GET.
301 Moved Permanently Переехать навсегда. Запрашиваемый ресурс был постоянно перемещен на новый URI, возвращенная информация будет включать в себя новый URI, а браузер будет автоматически направлен на новый URI.
302 Found Временный переезд. Клиенты должны продолжать использовать старый URI.
304 Not Modified Без изменений. Запрошенный ресурс не был изменен, и ресурс не будет возвращен, когда сервер вернет этот код состояния.
307 Temporary Redirect Временная переадресация. Перенаправление с использованием GET-запроса.
400 Bad Request В клиентском запросе есть синтаксическая ошибка, которую сервер не может понять.
401 Unauthorized Запрос требует аутентификации пользователя.
403 Forbidden Сервер понимает запрос запрашивающего клиента, но отказывается выполнять запрос.
404 Not Found Сервер не смог найти ресурс (веб-страницу) по запросу клиента.
500 Internal Server Error Внутренняя ошибка сервера, невозможно выполнить запрос.
502 Bad Gateway Сервер, работающий в качестве шлюза или прокси, получил недопустимый ответ от удаленного сервера при попытке выполнить запрос.
503 Service Unavailable Из-за перегрузки или обслуживания системы сервер временно не может обработать запрос клиента.

6-5 «Аякс» — кросс-домен

что такое кросс домен

  • Браузер имеет политику того же происхождения, которая не позволяет Ajax получать доступ к другим интерфейсам домена.
  • Междоменные условия: протокол, доменное имя, порт, если есть разница, то междоменное
  • Есть три вкладки, которые позволяют загружать ресурсы из разных источников.
    • <img src=xxx>, используемый для статистики RBI, веб-сайт статистики может быть другим доменом
    • <link href=xxx>, вы можете использовать CDN
    • <script src=xxx>, вы можете использовать CDN для JSONP

Междоменные соображения

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

Принцип реализации JSONP

  • нагрузкаcoding.IMO OC.com/lesson/115. …
  • Не обязательно файл 115.html на стороне сервера
  • Сервер может динамически генерировать файл и возвращать его по запросу.
  • По аналогии,<script src="http://coding.imooc.com/api.js">
  • Например, вашему веб-сайту необходим доступ к интерфейсу сети MOOC через домены.
  • МООК дает вам адресcoding.imooc.com/api.js
  • Формат возврата содержимого, такой какcallback({ x: 100, y: 200 })(может быть динамически сгенерирован)
<script>
window.callback = function(data) {
  // 这是我们跨域得到的信息
  console.log(data)
}
</script>
<script src="http://coding.imooc.com/api.js"></script>
<!-- 以上将返回 callback({ x: 100, y: 200 }) -->

Сервер устанавливает заголовок http

  • Еще один лаконичный способ решения междоменной проблемы требует, чтобы сервер выполнял
  • Но как взаимодействующая сторона мы должны знать этот метод
  • Это тенденция к решению междоменных проблем в будущем.
// 注意:不同后端语言的写法可能不一样

// 第二个参数填写允许跨域的域名称,不建议直接写 *
response.setHeader('Access-Control-Allow-Origin', 'http://a.com, http://b.com')
response.setHeader('Access-Control-Allow-Headers', 'X-Requested-With')
response.setHeader('Access-Control-Allow-Methods', 'PUT,POST,GET,DELETE,OPTIONS')

// 接收跨域的 Cookie
response.setHeader('Access-Control-Allow-Credentials', 'true')

Напишите Ajax, не полагаясь на сторонние библиотеки

var xhr = new XMLHttpRequest()
xhr.open('GET', '/api', false)
xhr.onreadystatechange = function() {
  if (xhr.readyState == 4) {
    if (xhr.status == 200) {
      alert(xhr.responseText)
    }
  }
}
xhr.send(null)

Несколько реализаций междоменного

  • JSONP
  • Настройка HTTP-заголовка на стороне сервера

Основные моменты

  • XMLHttpRequest
  • код состояния
  • перекрестный домен

6-6 Хранение

тема

  • Пожалуйста, опишите разницу между Cookie, sessionStorage и localStorage?

Точка знаний

  • Cookie
  • sessionStorage и localStorage

Cookie

  • Изначально используется для связи на стороне клиента и на стороне сервера.
  • Но у него есть функция локального хранилища, поэтому он "позаимствован"
  • использоватьdocument.cookieполучить и изменить

Недостатки файлов cookie для хранения

  • Хранилища слишком мало, всего 4 КБ
  • Переносятся все http запросы, что повлияет на оперативность получения ресурсов
  • API прост и должен быть инкапсулирован для использования.document.cookie

локальное хранилище и хранилище сессий

  • HTML5 предназначен для хранения, до 5 МБ
  • API прост и удобен в использовании,getItem(key),setItem(key, value)
  • В скрытом режиме iOS Safari localStorage.getItem сообщит об ошибке, рекомендуется использовать инкапсуляцию try-catch единообразно

Пожалуйста, опишите разницу между Cookie, sessionStorage и localStorage?

  • емкость
  • стоит ли нести его в запросе
  • простота использования API

Глава 7. Среда разработки

7-1 Введение

О среде разработки

  • Интервьюер хочет понять опыт интервьюируемого через среду разработки
  • Среда разработки, которая лучше всего отражает эффективность работы
  • Будет в основном в форме чата, а не конкретных вопросов

Среда разработки содержит

  • IDE (эффективность написания кода)
  • Git (управление версиями кода, совместная разработка несколькими людьми)
  • Модульный JS
  • упаковочный инструмент
  • Онлайн-процесс отката

7-2 IDE

IDE

  • WebStorm
  • Sublime
  • Код VS (рекомендуется)
  • Atom

7-3 Git — общие команды

Git

  • Формальные проекты требуют управления версиями кода
  • Большой проект требует многопользовательской разработки
  • Git и Linux — один автор
  • Сетевой сервер Git, например github
  • Как правило, код компании не является открытым исходным кодом и имеет собственный сервер Git.
  • Настройка Git-сервера не требует от вас особых знаний
  • Базовые операции с Git должны быть очень опытными

Общие команды Git

  • git add .
  • git checkout xxxВосстановить файлы
  • git commit -m 'xxx', отправить в локальный репозиторий
  • git push origin master, зафиксируйте в удаленном репозитории
  • git pull origin master, для загрузки файлов из удаленного репозитория
  • git branch, создать ветку
  • git checkout -b xxx/git checkout xxx, создать новую ветку/переключиться на другую ветку
  • git merge xxx, скопируйте предыдущую ветку сюда

7-4 Git — Демонстрация кода

без

7-5 Git — Демонстрация кода Многопользовательская совместная работа

многопользовательская разработка

  • Чтобы написать свои собственные функции, вы можете создать свою собственную ветку вместо того, чтобы вносить изменения в основную ветку, и, наконец, объединить ее.

шаг

  1. git checkout -b dev, создать ветку разработки
  2. vi a.jsИзмените содержимое (vi — это команда Linux,git statusПроверьте, не было ли оно изменено,git diffсмотрите измененный контент)
  3. git add .
  4. git commit -m 'update dev'
  5. git push origin dev, зафиксируйте в ветке dev удаленного репозитория
  6. Через полмесяца сливаем в ветку master
  7. git checkout master, переключиться на основную ветку
  8. git pull origin master, для скачивания файлов из ветки master удаленного репозитория
  9. git merge dev, скопируйте изменения из ветки dev в ветку master
  10. git push origin master, зафиксируйте в главной ветке удаленного репозитория

Дополнительные команды

  • cat 文件名, чтобы просмотреть содержимое файла
  • git diff, просмотреть измененный контент
  • git branch, чтобы увидеть ветку и в какой ветке она находится в данный момент
  • git status, чтобы увидеть, был ли файл изменен
  • vi 文件, создайте новый файл и откройте файл
  • esc + :wq, выйдите и сохраните файл

7-6 Модульный - AMD

Не используйте модульную

// util.js
function getFormatDate(date, type) {
  // type === 1 返回 2021-03-06
  // type === 2 返回 2021年3月6日
  // ...
}
// a-util.js
function aGetFormatDate(date) {
  // 要求返回 2021年3月6日格式
  return getFormatDate(date, 2)
}
// a.js
var dt = new Date()
console.log(aGetFormatDate(dt))
<script src="util.js"></script>
<script src="a-util.js"></script>
<script src="a.js"></script>
<!-- 1. 这些代码中的函数必须是全局变量,才能暴露给使用方。全局变量污染。 -->
<!-- 2. a.js 知道要引用 a-util.js ,但是他知道还需要依赖于 util.js 吗 -->

AMD

  • require.js
  • Глобальныйdefineфункция
  • Глобальныйrequireфункция
  • Зависимый JS будет загружаться автоматически и асинхронно

использовать require.js

// util.js
define(function() {
  return {
    getFormatDate: function(date, type) {
      if (type === 1) {
        return '2021-03-06'
      } else if (type === 2) {
        return '2021年3月6日'
      }
    }
  }
})
// a-util.js
define(['./util.js'], function(util) {
  return {
    aGetFormatDate: function(date) {
      return util.getFormatDate(date, 2)
    }
  }
})
// a.js
define(['./a-util.js'], function(aUtil) {
  return {
    printDate: function(date) {
      console.log(aUtil.aGetFormatDate(date))
    }
  }
})
// main.js
require(['./a.js'], function(a) {
  var date = new Date()
  a.printDate(date)
})
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>AMD</title>
</head>
<body>
  <script src="https://cdn.bootcdn.net/ajax/libs/require.js/2.3.6/require.min.js" data-main="./main.js"></script>
</body>
</html>

7-7 Модульность — демонстрация кода AMD

без

7-8 Модульность — CommonJS

CommonJS

  • Модульная спецификация Node.js в настоящее время активно используется во внешнем интерфейсе по следующим причинам:
  • Плагины и библиотеки, от которых зависит разработка интерфейса, можно получить из npm.
  • Высокоавтоматизированные инструменты сборки делают использование npm очень дешевым.
  • CommonJS не загружает JS асинхронно, а загружает его синхронно за один раз

Используйте CommonJS

// util.js
module.exports = {
  getFormatDate: function(date, type) {
    if (type === 1) {
      return '2021-03-06'
    } else if (type === 2) {
      return '2021年3月6日'
    }
  }
}
// a-util.js
var util = require('util.js')
module.exports = {
  aGetFormatDate: function(date) {
    return util.getFormatDate(date, 2)
  }
}

Сценарии использования AMD и CommonJS

  • Нужно асинхронно загружать JS, используйте AMD
  • После использования npm рекомендуется использовать CommonJS

Основные моменты

  • AMD
  • CommonJS
  • Разница между двумя

7-9 Инструменты сборки — установка Node.js

7-10 Инструменты сборки — установка Webpack

7-11 Инструменты сборки — Настройка Webpack

7-12 Инструменты сборки — Использование jQuery

7-13 Инструменты сборки — Минимизированный JS

7-14 Онлайн-откат — процесс онлайн-отката

7-15 линейная рулона - Linux Basic Command

Глава 8 Операционная среда

8-1 Введение

Рабочая среда

  • Браузер может получить содержимое страницы, перейдя по ссылке
  • По рисованию и рендерингу, показывая окончательный вид страницы
  • Какие вопросы нам необходимо рассмотреть на протяжении всего процесса?

Точка знаний

  • Загрузка страницы
  • оптимизация производительности
  • безопасность

8-2 Загрузка страницы — процесс рендеринга

тема

  • Подробный процесс от ввода URL до получения HTML
  • window.onloadа такжеDOMContentLoadedразница

Точка знаний

  • Форма загружаемого ресурса
  • Процесс загрузки ресурса
  • Процесс, с помощью которого браузер отображает страницу

Форма загружаемого ресурса

  • Введите URL (или перейдите на страницу), чтобы загрузить HTML
  • Загружать статические ресурсы в HTML

Процесс загрузки ресурса

  • Браузер получает IP-адрес доменного имени от DNS-сервера.
  • Отправьте HTTP-запрос на машину с этим IP-адресом
  • Сервер получает, обрабатывает и возвращает HTTP-запрос
  • Браузер получает возвращаемый контент

Процесс, с помощью которого браузер отображает страницу

  • Создание дерева DOM на основе структуры HTML
  • Создание CSSOM из CSS
  • Интегрируйте DOM и CSSOM для формирования дерева рендеринга
  • Начать рендеринг и отображение в соответствии с деревом рендеринга
  • встретить<script>, выполнит и заблокирует рендеринг

8-3 Загрузка страницы — несколько примеров

Зачем вставлять CSS в голову?

О: Обязательно сначала загрузите CSS, а затем выполните рендеринг, иначе он будет рендериться дважды, и взаимодействие с пользователем будет плохим.

Зачем ставить JS внизу тела?

О: Это не будет блокировать процесс рендеринга и улучшит производительность.

window.onloadа такжеDOMContentLoaded

window.addEventListener('load', function() {
  // 页面的全部资源加载完才会执行,包括图片、视频等
})
document.addEventListener('DOMContentLoaded', function() {
  // DOM 渲染完即可执行,此时图片、视频还可能没有加载完
})

8-4 Загрузка страницы - Ответы

Подробный процесс от ввода URL до получения HTML

  • Браузер получает IP-адрес доменного имени от DNS-сервера.
  • Отправьте HTTP-запрос на машину с этим IP-адресом
  • Сервер получает, обрабатывает и возвращает HTTP-запрос
  • Браузер получает возвращаемый контент

window.onloadа такжеDOMContentLoadedразница

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

8-5 Оптимизация производительности — стратегия оптимизации

оптимизация производительности

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

в общем

  • Используйте больше памяти, кэша или другие методы
  • Меньше вычислений ЦП, меньше сети

когда начать

  • Загружать страницы и статические ресурсы
  • рендеринг страницы

Оптимизация загрузки ресурсов

  • Сжатие и объединение статических ресурсов
  • Кэширование статических ресурсов
  • Используйте CDN для более быстрой загрузки ресурсов
  • Рендеринг с использованием серверной части SSR, данные выводятся непосредственно в HTML

Оптимизация рендеринга

  • CSS спереди, JS сзади
  • Ленивая загрузка (ленивая загрузка изображения, дополнительная загрузка раскрывающегося списка)
  • Сократите операции DOM, кэшируйте запросы DOM и выполняйте несколько операций вместе, насколько это возможно.
  • регулирование событий
  • Выполняйте операции заранее, например DOMContentLoaded.

8-6 Оптимизация производительности — несколько примеров

Консолидация ресурсов

<script src=a.js></script>
<script src=b.js></script>
<script src=c.js></script>
<script src="abc.js"></script>

тайник

  • Управление кешем по имени ссылки
  • Название ссылки меняется только при изменении содержимого

CDN

<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.min.js"></script>

Рендеринг с бэкендом SSR

  • Теперь Vue/React предлагает такую ​​концепцию
  • На самом деле JSP/PHP/ASP относятся к внутреннему рендерингу.

ленивая загрузка

<img id="img1" src="preview.png" data-realsrc="abc.png" />
<script>
  var img1 = document.getElementById('img1')
  img1.src = img1.getAttribute('data-realsrc')
</script>

Кэшировать DOM-запросы

// 未缓存 DOM 查询
var i
for (i = 0; i < document.getElementByTagName('p').length; i++) {
  
}

// 缓存了 DOM 查询
var pList = document.getElementByTagName('p')
var i
for (i = 0; i < pList.length; i++) {
  
}

Объединить вставку DOM

var listNode = document.getElementById('list')

// 要插入 10 个 li 标签
var frag = document.createDocumentFragment()
var x, li
for (x = 0; x < 10; x++) {
  li = document.createElement('li')
  li.innerHTML = 'List item ' + x
  frag.appendChild(li)
}
listNode.appendChild(frag)

регулирование событий

var textarea = document.getElementById('text')
var timeoutid
textarea.addEventListener('keyup', function() {
  if (timeoutid) {
    clearTimeout(timeoutid)
  }
  timeoutid = setTimeout(function() {
    // 触发 change 事件
  }, 100)
})

действовать рано

window.addEventListener('load', function() {
  // 页面的全部资源加载完才会执行,包括图片、视频等
})
document.addEventListener('DOMContentLoaded', function() {
  // DOM 渲染完即可执行,此时图片、视频还可能没有加载完
})

8-7 Безопасность — XSS

Точка знаний

  • XSS-атака с межсайтовым запросом
  • Подделка межсайтовых запросов XSRF

XSS

  • Напишите статью в блоге Sina и одновременно тайком вставьте абзац<script>
  • В коде атаки получите cookie и отправьте его на свой сервер
  • Опубликовать блог, кто-то просматривает содержимое блога
  • отправит файл cookie зрителя на сервер злоумышленника
  • Ключевые слова замены внешнего интерфейса, такие как replace<для&lt;,>для&gt;
  • замена серверной части

8-8 Безопасность — XSRF

XSRF

  • Вы вошли на сайт магазина и просматриваете товары
  • Платежный интерфейс этого веб-сайта — xxx.com/pay?id=100 , но верификации нет.
  • Затем вы получаете электронное письмо, скрывающее<img src="xxx.com/pay?id=100" />
  • Когда вы проверяете свою электронную почту, вы незаметно заплатили за нее
  • Увеличьте процесс проверки, такой как ввод отпечатка пальца, пароля, кода подтверждения SMS

8-9 Навыки интервью

резюме

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

во время интервью

  • Как вы относитесь к сверхурочной работе? Работать сверхурочно — это как брать деньги взаймы, а не помогать бедным
  • Не бросайте вызов интервьюеру, не проверяйте интервьюера
  • Научитесь удивлять интервьюера, но не слишком
  • Если у вас есть вопрос, на который вы не можете ответить, скажите, что вы знаете
  • Расскажите о своих слабостях — просто расскажите о том, чему вы научились в последнее время.

Глава 9 Моделирование реальных вопросов

  1. varа такжеlet,constразница

    отвечать:

    • varсинтаксис ES5,let,constсинтаксис ES6,varпеременный наддув
    • varа такжеletпеременная, модифицируемая,constпостоянна и не может быть изменена
    • let,constимеет блочную область действия,varнет
  2. typeofкакие типы возвращаются

    отвечать:

    • неопределенный, строка, число, логическое значение, символ
    • объект (примечание,typeof null === 'object')
    • function
  3. Перечисление принуждения и неявных преобразований типов

    отвечать:

    • Обязательный:parseInt,parseFloat,toStringЖдать
    • Неявный: if , логические операции, == , + объединение строк
  4. Сравнение глубины рукописного ввода, имитирующее lodashisEqual

    отвечать:

    // 判断是否是对象或数组
    function isObject(obj) {
      return typeof obj === 'object' && obj !== null
    }
    function isEqual(obj1, obj2) {
      if (!isObject(obj1) || !isObject(obj2)) {
        // 值类型(注意,参与 equal 的一般不会是函数)
        return obj1 === obj2
      }
      if (obj1 === obj2) {
        return true
      }
      // 两个都是对象或数组,而且不相等
      // 1. 先取出 obj1 和 obj2 的 keys ,比较个数
      const obj1Keys = Object.keys(obj1)
      const obj2Keys = Object.keys(obj2)
      if (obj1Keys.length !== obj2Keys.length) {
        return false
      }
      // 2. 以 obj1 为基准,和 obj2 一次递归比较
      for (let key in obj1) {
        if (!isEqual(obj1[key], obj2[key])) {
          return false
        }
      }
      // 3. 全相等
      return true
    }
    
    const obj1 = {
      a: 100,
      b: {
        x: 100,
        y: 200
      }
    }
    const obj2 = {
      a: 100,
      b: {
        x: 100,
        y: 200
      }
    }
    console.log(obj1 === obj2) // false
    console.log(isEqual(obj1, obj2)) // true
    
  5. splitа такжеjoinразница

    отвечать:

    '1-2-3'.split('-') // [1, 2, 3]
    [1, 2, 3].join('-') /// '1-2-3'
    
  6. массивpop,push,unshift,shiftчто делать

    отвечать:

    • Какова функция?
    • Каково возвращаемое значение?
    • Повлияет ли это на исходный массив?
    const arr = [10, 20, 30, 40]
    const result = arr.pop()
    console.log(result, arr) // 40, [10, 20, 30]
    
    const arr = [10, 20, 30, 40]
    const result = arr.push(50) // 返回 length
    console.log(result, arr) // 5, [10, 20, 30, 40, 50]
    
    const arr = [10, 20, 30, 40]
    const result = arr.unshift(5) // 返回 length
    console.log(result, arr) // 5, [5, 10, 20, 30, 40]
    
    const arr = [10, 20, 30, 40]
    const result = arr.shift()
    console.log(result, arr) // 10, [20, 30, 40]
    

    Чистая функция: 1. не изменяет исходный массив 2. возвращает массив

    // 纯函数
    const arr = [10, 20, 30, 40]
    
    const cArr = arr.concat([50, 60, 70]) // [10, 20, 30, 40, 50, 60, 70]
    const mArr = arr.map(item => item * 10) // [100, 200, 300, 400]
    const fArr = arr.filter(item => item > 20) // [30, 40]
    const sArr = arr.slice() // [10, 20, 30, 40]
    
    
    // 非纯函数
    // push 、pop 、shift 、unshift
    // forEach
    // some every reduce
    
  7. множествоsliceа такжеspliceразница

    отвечать:

    • функциональная разница,sliceэто ломтик,spliceсращивает
    • Параметры и возвращаемые значения
    • Это чистая функция?
    const arr = [10, 20, 30, 40, 50]
    
    // slice 是纯函数
    const sliceArr = arr.slice(1, 4)
    
    // splice 不是纯函数
    const spliceArr = arr.splice(1, 2, 'a', 'b', 'c')
    console.log(arr, spliceArr) // [10, "a", "b", "c", 40, 50],[20, 30]
    
  8. [10, 20, 30].map(parseInt)Каков результат возврата?

    отвечать:

    • mapпараметры и возвращаемое значение
    • parseIntпараметры и возвращаемое значение
    [10, 20, 30].map(parseInt)
    // 相当于
    [10, 20, 30].map((item, index) => {
      return parseInt(item, index)
    })
    // 分解为
    parseInt(10, 0) // 10
    parseInt(20, 1) // NaN
    parseInt(30, 2) // NaN
    
  9. В чем разница между получением и публикацией запроса Ajax?

    отвечать:

    • get обычно используется для операций запроса, а post обычно используется для операций отправки.
    • Параметр get наваривается на url, а пост помещается в тело запроса (объем данных может быть больше)
    • Безопасность, сообщение легко предотвратить CSRF
  10. Разница между вызовом функции и применением?

    отвечать:

    fn.call(this, p1, p2, p3)
    fn.apply(this, arguments)
    
  11. Что такое делегирование события (делегирование)?

    отвечать:

    function bindEvent(elem, type, selector, fn) {
      if (fn == null) {
        fn = selector
        selector = null
      }
      elem.addEventListener(type, function(e) {
        var target
        if (selector) {
          target = e.target
          if (target.matches(selector)) {
            fn.call(target, e)
          }
        } else {
          fn(e)
        }
      })
    }
    
    // 使用代理
    var div1 = document.getElementById('div1')
    bindEvent(div1, 'click', 'a', function(e) {
      console.log(this.innerHTML)
    })
    
    // 不使用代理
    var a = document.getElementById('a1')
    bindEvent(div1, 'click', function(e) {
      console.log(a.innerHTML)
    })
    
  12. Что такое замыкание и каковы его характеристики? Каковы негативные эффекты?

    отвечать:

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

    отвечать:

    • event.stopPropagation()
    • event.preventDefault()
  14. Как найти, добавить, удалить, переместить узлы DOM?

    отвечать:

    • getElementById,getElementsByTagName,getElementsByClassName,querySelectorAll
    • appendChild(добавить и переместить)
    • removeChild
    • parentNode,childNodes
  15. Как уменьшить манипуляции с DOM?

    отвечать:

    • Кэшировать результаты запроса DOM
    • Несколько манипуляций с DOM, объединенных в одну вставку
  16. Объясните, как работает JSONP и почему это не совсем Ajax?

    отвечать:

    • Политика одного и того же источника в браузере (на сервере нет политики одного и того же источника) и междоменная
    • Какие теги HTML могут обходить междоменные домены?
    • Как работает JSONP
  17. documentРазница между нагрузкой и готовностью

    отвечать:

    window.addEventListener('load', function() {
      // 页面的全部资源加载完才会执行,包括图片、视频等
    })
    document.addEventListener('DOMContentLoaded', function() {
      // DOM 渲染完即可执行,此时图片、视频还可能没有加载完
    })
    
  18. ==а также===разница

    отвечать:

    • ==попробую преобразовать тип
    • ===строгое равенство
    • Какие сценарии будут использоваться==?
  19. Разница между объявлением функции и выражением функции

    отвечать:

    • объявление функцииfunction fn() {}
    • функциональное выражениеconst fn = function() {}
    • Объявления функций предварительно загружаются перед выполнением кода, в то время как выражения функций не загружаются.
  20. new Object()а такжеObject.create()разница

    отвечать:

    • {}Эквивалентноnew Object(), прототип естьObject.prototype
    • Object.create(null)нет прототипа
    • Object.crate({...})Можно указать архетипы.
    const obj1 = {
      a: 10,
      b: 20,
      sum() {
        return this.a + this.b
      }
    }
    const obj2 = new Object({
      a: 10,
      b: 20,
      sum() {
        return this.a + this.b
      }
    })
    const obj3 = new Object(obj1)
    console.log(obj1 === obj2) // false
    console.log(obj1 === obj3) // true
    
    const obj4 = Object.create(null) // {} ,但没有原型
    const obj5 = new Object() // {}
    const obj6 = Object.create(obj1) // 创建一个空对象,把空对象的原型指向 obj1
    console.log(obj1 === obj6) // false
    console.log(obj1 === obj6.__proto__) // true
    
  21. оthisназвание сцены

    const User = {
      count: 1,
      getCount: function() {
        return this.count
      }
    }
    console.log(User.getCount()) // 1
    const func = User.getCount
    console.log(func()) // undefined
    
  22. Сценарные вопросы о области действия и свободных переменных (1)

    let i
    for (i = 1; i <= 3; i++) {
      setTimeout(function() {
        console.log(i)
      }, 0)
    }
    // 4
    // 4
    // 4
    
  23. Строка суждения начинается с буквы, за которой следует буквенно-цифровое подчеркивание, и имеет длину от 6 до 30.

    отвечать:

    const reg = /^[a-zA-Z]\w{5,29}$/
    
  24. Сценарные вопросы о области действия и свободных переменных (2)

    let a = 100
    function test() {
      alert(a) // 100
      a = 10
      alert(a) // 10
    }
    test()
    alert(a) // 10
    
  25. рукописная строкаtrimметод обеспечения совместимости браузера

    отвечать:

    String.prototype.trim = function() {
      return this.replace(/^\s+/, '').replace(/\s+$/, '')
    }
    // (原型、this 、正则表达式)
    
  26. Как получить максимальное значение среди нескольких чисел

    отвечать:

    function max() {
      const nums = Array.prototype.slice.call(arguments) // 变为数组
      let max = -Infinity
      nums.forEach(n => {
        if (n > max) {
          max = n
        }
      })
      return max
    }
    // 或者使用 Math.max()
    
  27. Как реализовать наследование с помощью JS?

    отвечать:

    • Наследование класса
    • наследование прототипа
  28. Как перехватывать исключения в JS-программах?

    отвечать:

    // 第一种方式
    try {
      // TODO
    } catch(error) {
      console.error(error) // 手动捕获
    } finally {
      // TODO
    }
    
    // 第二种方式
    // 自动捕获
    window.onerror = function(message, source, lineNum, colNum, error) {
      // 第一,对跨域的 JS ,如 CDN 的不会有详细的报错信息
      // 第二,对于压缩的 JS ,还要配合 SourceMap 反查到未压缩代码的行、列
    }
    
  29. Что такое JSON?

    отвечать:

    • JSON — это формат данных, по сути, строка
    • Формат JSON такой же, как и структура объектов JS, которая более удобна для языка JS.
    • window.JSONглобальный объект,JSON.stringifyа такжеJSON.parse
  30. Получить текущие параметры URL страницы

    отвечать:

    • традиционный способ, найтиlocation.search
    • новый API,URLSearchParams
    // 传统方式
    function query(name) {
      const search = location.search.substr(1)
      const reg = new RegExp(`(^|&)${name}=([^&]*)(&|$)`, 'i')
      const res = search.match(reg)
      if (res === null) {
        return null
      }
      return res[2]
    }
    
    // URLSearchParams
    function query(name) {
      const search = location.search
      const p = new URLSearchParams(search)
      return p.get(name)
    }
    
  31. Разбирать параметры URL в объекты JS

    отвечать:

    // 传统方式,分析 search
    function query2Obj() {
      const res = {}
      const search = location.search.substr(1) // 去掉前面的 ?
      search.split('&').forEach(paramStr => {
        const arr = paramStr.split('=')
        const [key, val] = arr
        res[key] = val
      })
      return res
    }
    
    // 使用 URLSearchParams
    function query2Obj() {
      const res = {}
      const pList = new URLSearchParams(location.search)
      pList.forEach((val, key) => {
        res[key] = val
      })
      return res
    }
    
  32. Рукописный массив faltern с учетом нескольких уровней

    отвечать:

    function flat(arr) {
      // 验证 arr 中,还有没有深层数组
      const isDeep = arr.some(item => item instanceof Array)
      if (!isDeep) {
        return arr
      }
      return flat(Array.prototype.concat.apply([], arr))
    }
    
    const res = flat([1, 2, [3, 4], [5, [6, 7]]])
    console.log(res) // [1, 2, 3, 4, 5, 6, 7]
    
  33. Дедупликация массива

    отвечать:

    • Традиционный способ, обход элементов один за другим для сравнения и дедупликации.
    • Использовать набор
    • Учитывайте вычислительную эффективность
    // 传统方式
    function unique(arr) {
      const res = []
      arr.forEach(item => {
        if (res.indexOf(item) < 0) {
          res.push(item)
        }
      })
      return res
    }
    console.log(unique([1, 2, 3, 1, 2, 3, 4])) // 1 2 3 4
    
    // 使用 Set(无序、不重复)
    function unique(arr) {
      const set = new Set(arr)
      return [...set]
    }
    console.log(unique([1, 2, 3, 1, 2, 3, 4])) // 1 2 3 4
    
  34. рукописная глубокая копия

    отвечать:

    function deepClone(obj = {}) {
      // 如果不是数组或对象,直接返回
      if (typeof obj !== 'object' || obj == null) {
        return obj
      }
      // 初始化返回结果
      let result
      if (obj instanceof Array) {
        result = []
      } else {
        result = {}
      }
      // 遍历数组或对象的属性
      for (let key in obj) {
        // 保证 key 不是原型的属性
        if (obj.hasOwnProperty(key)) {
          // 递归调用
          result[key] = deepClone(obj[key])
        }
      }
      // 返回结果
      return result
    }
    
    // 注意 Object.assign 不是深拷贝
    
  35. Ввести РАФ (requestAnimationFrame)

    отвечать:

    • Для плавной анимации частота обновления должна составлять 60 кадров в секунду, что составляет 16,67 мс для однократного обновления представления.
    • setTimeoutЧтобы обновить частоту вручную, в то время как браузер RAF автоматически управляет
    • В фоновых вкладках или скрытых фреймах RAF приостанавливается, покаsetTimeoutвсе еще выполнять
    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta http-equiv="X-UA-Compatible" content="IE=edge">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>setTimeout</title>
      <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.js"></script>
      <style>
        #div1, #div2 {
          width: 100px;
          height: 50px;
          margin-bottom: 20px;
          background-color: red;
        }
      </style>
    </head>
    <body>
      <div id="div1">setTimeout</div>
      <div id="div2">requestAnimateFrame</div>
      <script>
        const $div1 = $('#div1')
        let curWidth = 100
        const maxWidth = 640
        function animate() {
          curWidth += 3
          $div1.css('width', curWidth)
          if (curWidth < maxWidth) {
            setTimeout(animate, 16.7)
          }
        }
        animate()
    
        const $div2 = $('#div2')
        let curWidth2 = 100
        function animate2() {
          curWidth2 += 3
          $div2.css('width', curWidth2)
          if (curWidth2 < maxWidth) {
            window.requestAnimationFrame(animate2)
          }
        }
        animate2()
      </script>
    </body>
    </html>
    
  36. Как оптимизировать производительность интерфейса? Какие аспекты обычно учитываются?

    отвечать:

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