предисловие
Когда вы состаритесь и оглянетесь на свою жизнь, вы обнаружите, что когда вы уезжаете учиться за границу, когда вы решаете сделать свою первую карьеру, когда вы выбираете партнера и влюбляетесь, и когда вы выходите замуж, это на самом деле большая перемена судьбы. Просто я стоял в это время на развилке дорог и видел ситуацию в небе.День, когда вы сделали свой выбор, был в дневнике довольно унылым и обычным.В то время я думал, что это обычный день в жизни.
Проект, изменивший интервью --Карта интервью.
Осенний сезон найма Jin Jiu Yin Shi не за горами, и все должны быть готовы бросить вызов лучшим возможностям трудоустройства. Ну, интервью, безусловно, самая большая проблема.
Для собеседований обычное накопление, безусловно, необходимо, но подготовка перед собеседованием также имеет решающее значение.
Несколько месяцев назад я лично сформировал небольшую команду и почти полгода искал вопросы для интервью с крупных заводов, отсняли и записали около сотни пунктов знаний, и все они были переведены на английский язык. Сегодня первая версия, наконец, открыта, и общее количество слов достигло более 100 000 слов. Каждый член команды — инженер с передовой, а также есть большой парень из Google.
Можно сказать, что мы уверены, что сможем сделать этот проект номером 1 в вопросах, связанных с интервью.Поскольку все содержание не было скопировано ни из каких книг, каждая точка знаний была подробно рассмотрена, прежде чем она будет написана. Позже будет добавлено больше контента, чтобы максимально охватить большинство точек знаний.
Мы думаем, что вопросы слепого обратного тестирования малопригодны. Только когда вы ознакомитесь с каждым пунктом знаний и овладеете им, вы сможете преодолеть все препятствия на собеседовании. Эта карта на данный момент содержит около 100 высокочастотных точек знаний, Будь то подготовка к собеседованию или заполнение вакансий в обычной учебе, мы уверены, что она обязательно поможет всем. Текущий контент включает в себя JS, сеть, браузер, оптимизацию производительности, безопасность, фреймворк, Git, структуру данных, алгоритм и т. д., будь то базовый или расширенный, или интерпретацию исходного кода, вы можете быть удовлетворены этой картой Ответ , Я надеюсь, что эта карта интервью поможет вам лучше подготовиться к интервью.
На складе будет постоянно обновляться контент, последний будет содержать больше контента, такого как: дизайн системы, цепочка блоков, эксплуатация и обслуживание, бэкэнд, и, конечно, это не моя сильная сторона, у меня будет хороший опыт в этом область пригласить друзей, чтобы написать содержание.
контур
Поиск работы
В последнее время я ищу возможности трудоустройства, если есть хорошая работа в Ханчжоу, пожалуйста, свяжитесь со мной.zx597813039@gmail.com.
Некоторый предварительный просмотр контента
MVVM
MVVM состоит из следующих трех компонентов
- Вид: интерфейс
- Модель: модель данных
- ViewModel: как мост, отвечающий за связь View и Model.
В период JQuery, если вам нужно обновить пользовательский интерфейс, вам нужно получить соответствующий DOM, а затем обновить пользовательский интерфейс, чтобы данные и бизнес-логика были тесно связаны со страницей.
В MVVM пользовательский интерфейс управляется данными. После изменения данных соответствующий пользовательский интерфейс будет соответствующим образом обновлен. Если пользовательский интерфейс изменится, соответствующие данные также будут изменены. Таким образом, вы можете заботиться только о потоке данных при бизнес-обработке, не имея возможности напрямую работать со страницей. ViewModel заботится только об обработке данных и бизнесе, а не о том, как View обрабатывает данные.В этом случае View и Model могут быть независимыми, ни одна из сторон не обязательно должна изменять другую сторону, а некоторая повторно используемая логика помещается в ViewModel , и несколько представлений могут повторно использовать эту ViewModel.
В MVVM ядром является двусторонняя привязка данных, такая как обнаружение грязных данных в Angluar и перехват данных в Vue.
обнаружение грязных данных
Когда заданное событие срабатывает, оно войдет в режим обнаружения грязных данных, а затем вызовет$digest
Переберите все наблюдатели данных, чтобы определить, отличается ли текущее значение от предыдущего значения. Если обнаружено изменение, он вызовет$watch
функцию, затем вызовите снова$digest
Цикл, пока не будет найдено никаких изменений. Цикл не менее двух раз и не более десяти раз.
Хотя обнаружение грязных данных имеет проблему неэффективности, оно может выполнить задачу независимо от того, как данные изменены, но есть проблема с двусторонней привязкой в Vue. А обнаружение грязных данных может обнаруживать обновленные значения пакетами, а затем единообразно обновлять пользовательский интерфейс, что значительно сокращает количество операций DOM. Следовательно, неэффективность также относительна, а это означает, что благожелательный видит благожелательный, а мудрый видит мудрость.
захват данных
Vue используется внутриObeject.defineProperty()
Для достижения двусторонней привязки через эту функцию можно прослушиватьset
а такжеget
мероприятие.
var data = { name: 'yck' }
observe(data)
let name = data.name // -> get value
data.name = 'yyy' // -> change value
function observe(obj) {
// 判断类型
if (!obj || typeof obj !== 'object') {
return
}
Object.keys(data).forEach(key => {
defineReactive(data, key, data[key])
})
}
function defineReactive(obj, key, val) {
// 递归子属性
observe(val)
Object.defineProperty(obj, key, {
enumerable: true,
configurable: true,
get: function reactiveGetter() {
console.log('get value')
return val
},
set: function reactiveSetter(newVal) {
console.log('change value')
val = newVal
}
})
}
Приведенный выше код просто реализует, как отслеживать данныеset
а такжеget
событий, но этого недостаточно, вам также необходимо добавить публикацию и подписку на свойства, когда это необходимо
<div>
{{name}}
</div>
При разборе приведенного выше кода шаблона столкнитесь{{name}}
даст атрибутыname
Добавьте публикацию-подписку.
// 通过 Dep 解耦
class Dep {
constructor() {
this.subs = []
}
addSub(sub) {
// sub 是 Watcher 实例
this.subs.push(sub)
}
notify() {
this.subs.forEach(sub => {
sub.update()
})
}
}
// 全局属性,通过该属性配置 Watcher
Dep.target = null
function update(value) {
document.querySelector('div').innerText = value
}
class Watcher {
constructor(obj, key, cb) {
// 将 Dep.target 指向自己
// 然后触发属性的 getter 添加监听
// 最后将 Dep.target 置空
Dep.target = this
this.cb = cb
this.obj = obj
this.key = key
this.value = obj[key]
Dep.target = null
}
update() {
// 获得新值
this.value = this.obj[this.key]
// 调用 update 方法更新 Dom
this.cb(this.value)
}
}
var data = { name: 'yck' }
observe(data)
// 模拟解析到 `{{name}}` 触发的操作
new Watcher(data, 'name', update)
// update Dom innerText
data.name = 'yyy'
Далее, даdefineReactive
функция преобразования
function defineReactive(obj, key, val) {
// 递归子属性
observe(val)
let dp = new Dep()
Object.defineProperty(obj, key, {
enumerable: true,
configurable: true,
get: function reactiveGetter() {
console.log('get value')
// 将 Watcher 添加到订阅
if (Dep.target) {
dp.addSub(Dep.target)
}
return val
},
set: function reactiveSetter(newVal) {
console.log('change value')
val = newVal
// 执行 watcher 的 update 方法
dp.notify()
}
})
}
Вышеприведенное реализует простую двустороннюю привязку.Основная идея заключается в том, чтобы один раз вручную вызвать геттер свойства, чтобы реализовать добавление публикации и подписки.
Прокси против Obeject.defineProperty
Obeject.defineProperty
Несмотря на то, что удалось добиться двусторонней привязки, он все еще имеет недостатки.
- Только перехват данных может быть выполнен для свойств, поэтому вам нужно глубоко пройти весь объект
- Изменения в данных не могут быть отслежены для массивов
Хотя это правда, что Vue может обнаруживать изменения в данных массива, на самом деле это хак, и он также имеет недостатки.
const arrayProto = Array.prototype
export const arrayMethods = Object.create(arrayProto)
// hack 以下几个函数
const methodsToPatch = [
'push',
'pop',
'shift',
'unshift',
'splice',
'sort',
'reverse'
]
methodsToPatch.forEach(function (method) {
// 获得原生函数
const original = arrayProto[method]
def(arrayMethods, method, function mutator (...args) {
// 调用原生函数
const result = original.apply(this, args)
const ob = this.__ob__
let inserted
switch (method) {
case 'push':
case 'unshift':
inserted = args
break
case 'splice':
inserted = args.slice(2)
break
}
if (inserted) ob.observeArray(inserted)
// 触发更新
ob.dep.notify()
return result
})
})
Напротив, Proxy не имеет вышеописанных проблем: он изначально поддерживает мониторинг изменений массива и может напрямую перехватывать весь объект, поэтому Vue также будет использовать Proxy для замены Obeject.defineProperty в следующей основной версии.
let onWatch = (obj, setBind, getLogger) => {
let handler = {
get(target, property, receiver) {
getLogger(target, property)
return Reflect.get(target, property, receiver);
},
set(target, property, value, receiver) {
setBind(value);
return Reflect.set(target, property, value);
}
};
return new Proxy(obj, handler);
};
let obj = { a: 1 }
let value
let p = onWatch(obj, (v) => {
value = v
}, (target, property) => {
console.log(`Get '${property}' = ${target[property]}`);
})
p.a = 2 // bind `value` to `2`
p.a // -> Get 'a' = 2
Принцип маршрутизации
Front-end роутинг на самом деле очень прост в реализации, суть в том, чтобы отслеживать изменения URL, затем сопоставлять правила роутинга, отображать соответствующую страницу и не нужно обновляться. В настоящее время существует только два способа реализации маршрутизации, используемой одной страницей.
- хэш-режим
- режим истории
www.test.com/#/
URL-адрес хэша, когда#
При изменении последующего хеш-значения данные не будут запрашиваться с сервера.hashchange
События для прослушивания изменений в URL, чтобы перейти на страницу.
Режим истории — это новая функция в HTML5, которая красивее, чем Hash URL.
встроенный тип
JS делится на семь встроенных типов, семь встроенных типов делятся на два основных типа: базовые типы и объекты (Object).
Существует шесть основных типов:null
,undefined
,boolean
,number
,string
,symbol
.
Среди них числовой тип JS — это тип с плавающей запятой, а целочисленный тип отсутствует. А тип с плавающей запятой реализован на основе стандарта IEEE 754, а некоторыеBug.NaN
также принадлежатnumber
тип иNaN
не равно себе.
Для базовых типов, если используется литеральный метод, тогда переменная является просто литералом и будет преобразована в соответствующий тип только при необходимости.
let a = 111 // 这只是字面量,不是 number 类型
a.toString() // 使用时候才会转换为对象类型
Объект (Object) является ссылочным типом, и при использовании он столкнется с проблемой поверхностного копирования и глубокого копирования.
let a = { name: 'FE' }
let b = a
b.name = 'EF'
console.log(a.name) // EF
Typeof
typeof
Для примитивных типов, кромеnull
оба отображают правильный тип
typeof 1 // 'number'
typeof '1' // 'string'
typeof undefined // 'undefined'
typeof true // 'boolean'
typeof Symbol() // 'symbol'
typeof b // b 没有声明,但是还会显示 undefined
typeof
Для объектов отображаются все, кроме функцийobject
typeof [] // 'object'
typeof {} // 'object'
typeof console.log // 'function'
дляnull
Например, хотя это примитивный тип, он покажетobject
, это давний баг
typeof null // 'object'
ПС: Почему так происходит? Потому что в начальной версии JS использовалась 32-битная система, и информация о типе переменной хранилась в младших битах из соображений производительности.000
Однако, начиная представлять объектnull
представлен как все нули, поэтому он ошибочно оценивается какobject
. Хотя текущий внутренний код оценки типа изменился, ошибка была передана.
Если мы хотим получить правильный тип переменной, мы можем передатьObject.prototype.toString.call(xx)
. Таким образом, мы можем получить что-то вроде[Object Type]
Нить.
let a
// 我们也可以这样判断 undefined
a === undefined
// 但是 undefined 不是保留字,能够在低版本浏览器被赋值
let undefined = 1
// 这样判断就会出错
// 所以可以用下面的方式来判断,并且代码量更少
// 因为 void 后面随便跟上一个组成表达式
// 返回就是 undefined
a === void 0
преобразование типов
превратить логическое значение
В условном решении, за исключениемundefined
,null
,false
,NaN
,''
,0
,-0
, все остальные значения преобразуются вtrue
, включая все объекты.
объект к примитивному типу
Когда объект преобразует примитивный тип, он сначала вызываетvalueOf
тогда позвониtoString
. И вы можете переопределить эти два метода.
let a = {
valueOf() {
return 0
}
}
Четыре оператора
Только когда одно из дополнений является строковым типом, другое будет преобразовано в строковый тип. Пока одна из других операций является числом, другая сторона преобразуется в число. А операция сложения запускает три преобразования типов: преобразование значения в примитив, преобразование в число, преобразование в строку.
1 + '1' // '11'
2 * '2' // 4
[1, 2] + [2, 1] // '1,22,1'
// [1, 2].toString() -> '1,2'
// [2, 1].toString() -> '2,1'
// '1,2' + '2,1' = '1,22,1'
Обратите внимание на это выражение для знака плюс'a' + + 'b'
'a' + + 'b' // -> "aNaN"
// 因为 + 'b' -> NaN
// 你也许在一些代码中看到过 + '1' -> 1
==
оператор
на картинке вышеtoPrimitive
Это объект базового типа.
Обычно рекомендуется===
Оценивайте два значения, но если вы хотите знать, является ли значениеnull
, вы можете пройтиxx == null
сравнивать.
Вот анализ темы[] == ![] // -> true
, вот почему это выражениеtrue
Шаг
// [] 转成 true,然后取反变成 false
[] == false
// 根据第 8 条得出
[] == ToNumber(false)
[] == 0
// 根据第 10 条得出
ToPrimitive([]) == 0
// [].toString() -> ''
'' == 0
// 根据第 6 条得出
0 == 0 // -> true
оператор сравнения
- Если это объект, передать
toPrimitive
Конвертировать объект - Если это строка, передать
unicode
Индекс персонажа для сравнения
Нет публики
Todo
- Полный CSS-контент
- Полный контент Webapck
- Заполните соответствующее содержимое апплета
- Завершите содержание о фреймворке
Ожидается, что указанный выше контент будет обновлен в сентябре. Приглашаем вас принять участие в создании этой карты.
Карта интервьюАдрес проекта, если вы считаете, что проект неплохой, вы можете нажать на маленькую звездочку, чтобы поддержать нас, ваша поддержка является источником нашего обновления.