BAT大牛帶你橫掃前端面試js

  1. 值類(lèi)型

(1)值類(lèi)型賦值的時(shí)候不會(huì)相互影響

<pre class="prettyprint hljs javascript" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; word-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px;">// 值類(lèi)型
let a = 100
let b = a
a = 200
console.log(b) // 100
復(fù)制代碼</pre>

image

(2)常見(jiàn)值類(lèi)型

<pre class="prettyprint hljs javascript" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; word-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px;">let a // Undefinded
const s = 'abc' // String
const n = 100 // Number
const b = true // Boolean
const s = Symbol('s') // Symbol
復(fù)制代碼</pre>

  1. 引用類(lèi)型

(1)引用類(lèi)型賦值的時(shí)候,賦值的是引用地址芜抒,會(huì)相互影響熬甫。引用類(lèi)型賦值地址主要是考慮計(jì)算機(jī)性能問(wèn)題

<pre class="prettyprint hljs javascript" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; word-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px;">// 引用類(lèi)型
let a = { age: 20 }
let b = a
b.age = 21
console.log(a.age) // 21
復(fù)制代碼</pre>

image

棧從上往下添加數(shù)據(jù)吧凉,堆從下往上添加數(shù)據(jù)

(2)常見(jiàn)引用類(lèi)型

<pre class="prettyprint hljs php" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; word-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px;">const obj = { x: 100 } // 對(duì)象
const arr = [1, 2, 3] // 數(shù)組

// 特殊引用類(lèi)型,指針指向空地址(《JS高級(jí)程序設(shè)計(jì)》中將null歸為值類(lèi)型)
const n = null

// 特殊引用類(lèi)型况增,但不用于存儲(chǔ)數(shù)據(jù),所以沒(méi)有‘拷貝、復(fù)制函數(shù)’這一說(shuō)
function fn() {}
復(fù)制代碼</pre>

2.1.2 typeof運(yùn)算符

<pre class="prettyprint hljs javascript" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; word-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px;">// 判斷所有值類(lèi)型
let a; typeof a // 'undefinded'
const s = 'abc'; typeof s // 'string'
const n = 100; typeof n // 'number'
const b = true; typeof b // 'boolean'
const s = Symbol('s'); typeof s // 'symbol'

// 能判斷函數(shù)
typeof console.log // 'function'
typeof function () {} // 'function'

// 能識(shí)別引用類(lèi)型(不能再識(shí)別的更細(xì))
typeof null // 'object'
typeof ['a', 'b'] // 'object'
typeof { x: 100 } // 'object'
復(fù)制代碼</pre>

2.1.3 深拷貝

<pre class="prettyprint hljs javascript" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; word-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px;">/**

  • 深拷貝
    */
    const obj1 = {
    name: 'Mary',
    age: 21,
    address: {
    city: 'Beijing'
    },
    arr: [1, 2, 3]
    }
    const obj2 = deepClone(obj1)
    obj2.address.city = 'Shanghai'
    obj2.arr[0] = 0
    console.log(obj1, obj2)

function deepClone(obj = {}) {
if (typeof obj !== 'object' || obj == null) {
return obj
}
// 初始化返回結(jié)果
let result
if (obj instanceof Array) {
result = []
} else {
result = {}
}
for(let key in obj) {
if (obj.hasOwnProperty(key)) { // 保證key不是原型的屬性
result[key] = deepClone(obj[key]) // 遞歸調(diào)用
}
}
return result
}
復(fù)制代碼</pre>

image

2.2 變量計(jì)算-類(lèi)型轉(zhuǎn)換

2.2.1 字符串拼接

<pre class="prettyprint hljs go" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; word-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px;">const a = 100 + 10 // 110
const b = 100 + '10' // '10010'
const c = true + '10' // 'true10'
復(fù)制代碼</pre>

2.2.2 == 運(yùn)算符

<pre class="prettyprint hljs javascript" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; word-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px;">100 == '100' // true
0 == '' // true
0 == false // true
false == '' // true
null == undefined // true
復(fù)制代碼</pre>

<pre class="prettyprint hljs verilog" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; word-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px;">// 除了 == null之外像街,其他一律都用 ===
const obj = { x: 100 }
if (obj.a == null) {}
// 相當(dāng)于:
// if (obj.a === null || obj.a === undefined)
復(fù)制代碼</pre>

2.2.3 if語(yǔ)句和邏輯運(yùn)算

  • truly變量:!!a === true的變量
  • falsely變量:!!a === false的變量

<pre class="prettyprint hljs erlang-repl" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; word-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px;">// 以下是falsely變量。除此之外都是truly變量
!!0 === false
!!NaN === false
!!'' === false
!!null === false
!!undefined === false
!!false === false
復(fù)制代碼</pre>

  1. if語(yǔ)句

<pre class="prettyprint hljs xquery" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; word-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px;">// if語(yǔ)句判斷的不是true還是false晋渺,而是truly變量或falsely變量
// truly變量
const a = true
if (a) {}
const b = 100
if (b) {}

// falsely變量
const c = ''
if (c) {}
const d = null
if (d) {}
let e
if (e) {}
復(fù)制代碼</pre>

  1. 邏輯判斷

<pre class="prettyprint hljs javascript" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; word-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px;">// 邏輯判斷也是判斷truly變量和falsely變量
console.log(10 && 0) // 0
console.log('' || 'abc') // 'abc'
console.log(!window.abc) // true
復(fù)制代碼</pre>

三镰绎、題目解析

3.1 typeof 能判斷哪些類(lèi)型

  • 識(shí)別所有值類(lèi)型
  • 識(shí)別函數(shù)
  • 判斷是否是引用類(lèi)型(不可再細(xì)分)

3.2 何時(shí)使用=== 何時(shí)使用==

== 會(huì)轉(zhuǎn)換數(shù)據(jù)類(lèi)型,嘗試使兩端相等木西,因此最好使用 ===

<pre class="prettyprint hljs verilog" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; word-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px;">// 除了 == null 之外畴栖,其他一律都用 ===
const obj = { x: 100 }
if (obj.a == null) {}
// 相當(dāng)于:
// if (obj.a === null || obj.a === undefined)
復(fù)制代碼</pre>

3.3 值類(lèi)型和引用類(lèi)型的區(qū)別

面試題:

<pre class="prettyprint hljs javascript" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; word-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px;">const obj1 = { x: 100, y: 200 }
const obj2 = obj1
let x1 = obj1.x
obj2.x = 101
x1 = 102
console.log(obj1) // { x: 101, y: 200 }
復(fù)制代碼</pre>

  • 存儲(chǔ)位置不一樣
    • 值類(lèi)型存放在棧內(nèi)存中
    • 引用類(lèi)型在堆內(nèi)存中開(kāi)辟一個(gè)空間,存儲(chǔ)具體的值八千,而在棧內(nèi)存中存儲(chǔ)的是指向該值的地址

3.4 手寫(xiě)深拷貝

  • 注意判斷值類(lèi)型和引用類(lèi)型
  • 注意判斷是數(shù)組還是對(duì)象
  • 遞歸

具體代碼見(jiàn)2.1.3 深拷貝

原型和原型鏈

一吗讶、題目

1.1 如何準(zhǔn)確判斷一個(gè)變量是不是數(shù)組燎猛?

1.2 手寫(xiě)一個(gè)簡(jiǎn)易的jQuery,考慮插件和擴(kuò)展性

1.3 class的原型本質(zhì)照皆,怎么理解重绷?

二、知識(shí)點(diǎn)

2.1 class和繼承

2.1.1 class

  • constructor
  • 屬性
  • 方法

<pre class="prettyprint hljs javascript" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; word-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px;">// 類(lèi)
class Student {
constructor(name, number) {
this.name = name
this.number = number
}
sayHi () {
console.log(姓名:${this.name} 學(xué)號(hào):${this.number})
}
}
// 通過(guò)類(lèi) new 對(duì)象/實(shí)例
const tom = new Student('Tom', 21)
console.log(tom.name)
console.log(tom.number)
tom.sayHi()
復(fù)制代碼</pre>

2.1.2 繼承

  • extends
  • super
  • 擴(kuò)展和重寫(xiě)方法

<pre class="prettyprint hljs javascript" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; word-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px;">// Student繼承了People膜毁,People繼承了Object
// 父類(lèi)
class People {
constructor(name) {
this.name = name
}
eat () {
console.log(${this.name} eat something)
}
}
// 子類(lèi)
class Student extends People {
constructor(name, number) {
super(name);
this.number = number
}
sayHi () {
console.log(姓名:${this.name} 學(xué)號(hào):${this.number})
}
}
// 子類(lèi)
class Teacher extends People {
constructor(name, major) {
super(name)
this.major = major
}
teach () {
console.log(${this.name} 教授:${this.major})
}
}
// 通過(guò)類(lèi) new 對(duì)象/實(shí)例
const tom = new Student('Tom', 21)
console.log(tom.name)
console.log(tom.number)
tom.sayHi()
tom.eat()

// 通過(guò)類(lèi) new 對(duì)象/實(shí)例
const teacherWang = new Teacher('Wang', 'Math')
console.log(teacherWang.name)
console.log(teacherWang.major)
teacherWang.teach()
teacherWang.eat()
復(fù)制代碼</pre>

2.2 類(lèi)型判斷 instanceof

instanceof 可以判斷變量屬于哪個(gè)class或構(gòu)造函數(shù)

<pre class="prettyprint hljs javascript" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; word-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px;">tom instanceof Student // true
tom instanceof People // true
tom instanceof Object // true

[] instanceof Array // true
[] instanceof Object // true

{} instanceof Object // true
復(fù)制代碼</pre>

2.3 原型和原型鏈

2.3.1 原型

<pre class="prettyprint hljs javascript" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; word-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px;">// class實(shí)際上是函數(shù)昭卓,可見(jiàn)是語(yǔ)法糖
typeof People // 'function'
typeof Student // 'function'

// 隱式原型和顯示原型
console.log(tom.proto)
console.log(Student.prototype)
console.log(tom.proto === Student.prototype)
復(fù)制代碼</pre>

image

原型關(guān)系:

  • 每個(gè)class都有顯示原型prototype
  • 每個(gè)實(shí)例都有隱式原型proto
  • 實(shí)例的proto指向?qū)?yīng)class的prototype

基于原型的執(zhí)行規(guī)則

獲取屬性tom.name或執(zhí)行tom.sayHi()時(shí),

  1. 先在自身屬性和方法尋找
  2. 如果找不到則自動(dòng)去proto中尋找

2.3.2 原型鏈

<pre class="prettyprint hljs elm" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; word-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px;">console.log(Student.prototype.proto)
console.log(People.prototype)
console.log(People.prototype === Student.prototype.proto)
復(fù)制代碼</pre>

image

再看instanceof:

tom instanceof People tom的隱式原型沿著原型鏈瘟滨,一路往上查找候醒,能否找到People的顯示原型,若能找到室奏,則返回 true

重要提示火焰!

  1. class是ES6語(yǔ)法規(guī)范,由ECMA委員會(huì)發(fā)布
  2. ECMA只規(guī)定語(yǔ)法規(guī)則胧沫,即我們代碼的書(shū)寫(xiě)規(guī)范昌简,不規(guī)定如何實(shí)現(xiàn)
  3. 以上實(shí)現(xiàn)方式否是V8引擎的實(shí)現(xiàn)方式,也是主流的

三绒怨、題目解答

3.1 如何準(zhǔn)確判斷一個(gè)變量是不是數(shù)組纯赎?

  • a instanceof Array

3.2 手寫(xiě)一個(gè)簡(jiǎn)易的jQuery,考慮插件和擴(kuò)展性

<pre class="prettyprint hljs javascript" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; word-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px;">class jQuery {
constructor(selector) {
const result = document.querySelectorAll(selector)
const length = result.length
for(let i = 0;i < length; i++) {
this[i] = result[i]
}
this.length = length
this.selector = selector
}
get(index) {
return this[index]
}
each(fn) {
for(let i = 0; i < this.length; i++) {
const elem = this[i]
fn(elem)
}
}
on(type, fn) {
return this.each(elem => {
elem.addEventListener(type, fn, false)
})
}
}
// 擴(kuò)展方式1:插件
jQuery.prototype.dialog = function (info) {
alert(info)
}

// 擴(kuò)展方式2:'造輪子'
class myJQuery extends jQuery {
constructor(selector) {
super(selector);
}
// 擴(kuò)展自己的方法
addClass(className) {

}
style (data) {

}
}

const p = new jQuery('p')p.get(0)
p.each((elem) => console.log(elem.innerHTML))p.on('click', () => alert('clicked'))
$p.dialog('sth')
復(fù)制代碼</pre>

3.3 class的原型本質(zhì)南蹂,怎么理解犬金?

  • 原型和原型鏈的圖示
    • 每個(gè)class都有顯示原型prototype
    • 每個(gè)實(shí)例都有隱式原型proto
    • 實(shí)例的proto指向?qū)?yīng)class的prototype
  • 屬性和方法的執(zhí)行規(guī)則
    • 先在自身屬性和方法尋找
    • 如果找不到則自動(dòng)去proto中尋找

作用域和閉包

一、題目

1.1 this的不同應(yīng)用場(chǎng)景六剥,如何取值晚顷?

1.2 手寫(xiě)bind函數(shù)

1.3 實(shí)際開(kāi)發(fā)中閉包的應(yīng)用場(chǎng)景,舉例說(shuō)明

1.4 創(chuàng)建10個(gè)a標(biāo)簽疗疟,點(diǎn)擊的時(shí)候彈出來(lái)對(duì)應(yīng)的序號(hào)

二该默、知識(shí)點(diǎn)

2.1 作用域和自由變量

image

2.1.1作用域

作用域代表了一個(gè)變量的合法使用范圍,如上圖紅框所示策彤,若變量在所在紅框之外是無(wú)法使用的栓袖。 作用域分為:

  • 全局作用域:代碼中定義一個(gè)變量,不受函數(shù)約束店诗,在全局均可使用裹刮,如window對(duì)象,document對(duì)象
  • 函數(shù)作用域:任何定義在函數(shù)體內(nèi)的變量或者函數(shù)都將處于函數(shù)作用域中庞瘸,跳出該作用域外捧弃,變量無(wú)法使用
  • 塊級(jí)作用域(ES6新增)

<pre class="prettyprint hljs javascript" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; word-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px;">// 塊級(jí)作用域
if (true) {
let a = 1
}
console.log(a) // 報(bào)錯(cuò)
復(fù)制代碼</pre>

2.1.2 自由變量

  • 一個(gè)變量在當(dāng)前作用域沒(méi)有定義,但被使用了
  • 向上級(jí)作用域擦囊,一層一層依次尋找塔橡,直至找到為止
  • 如果到了全局作用域都沒(méi)找到梅割,則報(bào)錯(cuò) xx is not defined

如對(duì)于function fn3() {}中,a,a1,a2均屬于自由變量

2.2 閉包

作用域應(yīng)用的特殊情況葛家,有兩種表現(xiàn):

  1. 函數(shù)作為參數(shù)被傳遞

<pre class="prettyprint hljs php" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; word-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px;">// 函數(shù)作為參數(shù)
function print(fn) {
const a = 200
fn()
}
const a = 100
function fn() {
console.log(a)
}
print(fn) // 100

復(fù)制代碼</pre>

  1. 函數(shù)作為返回值被返回

<pre class="prettyprint hljs javascript" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; word-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px;">// 函數(shù)作為返回值
function create() {
const a = 100
return function () {
console.log(a)
}
}
const fn = create()
const a = 200
fn() // 100
復(fù)制代碼</pre>

所有的自由變量的查找户辞,是在函數(shù)【定義】的地方,向上級(jí)作用域查找癞谒,不是在執(zhí)行的地址5琢恰!弹砚!

2.3 this

2.3.1 this使用場(chǎng)景有:

  • 作為普通函數(shù):this指向全局對(duì)象(瀏覽器是window)双仍,嚴(yán)格模式中,表現(xiàn)為undefined
  • 使用call apply bind:this指向綁定的對(duì)象上
  • 作為對(duì)象方法被調(diào)用:this指向調(diào)用函數(shù)的對(duì)象
  • 在class方法中調(diào)用:this指向?qū)?yīng)的實(shí)例
  • 箭頭函數(shù):所有的箭頭函數(shù)都沒(méi)有自己的this桌吃,都指向上級(jí)作用域(箭頭函數(shù)本身不支持this)

2.3.2 this取什么值朱沃,是在函數(shù)【執(zhí)行】的時(shí)候確定的,不是在函數(shù)定義的時(shí)候

<pre class="prettyprint hljs javascript" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; word-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px;">function fn1() {
console.log(this)
}
fn1() // window

fn1.call({ x: 100 }) // { x: 100 }

const fn2 = fn1.bind({ x: 200 })
fn2() // { x: 200 }

const zhangsan = {
name: '張三',
sayHi() {
console.log(this) // this即當(dāng)前對(duì)象
},
wait() {
setTimeout(function() {
console.log(this) // function() {}是由setTimeout觸發(fā)了執(zhí)行(作為一個(gè)普通函數(shù)被執(zhí)行)茅诱,而非作為zhangsan的對(duì)象方法被執(zhí)行逗物,因此this === window
}, 1000)
},
waitAgain() {
setTimeout(() => {
console.log(this) // this即當(dāng)前對(duì)象
}, 1000)
}
}
zhangsan.sayHi()
zhangsan.wait()
zhangsan.waitAgain()

class People {
constructor(name, age) {
this.name = name
this.age = age
}
sayHi() {
console.log(this)
}
}
const zhangsan = new People('張三', 20)
zhangsan.sayHi() // zhangsan 對(duì)象
復(fù)制代碼</pre>

三、題目解答

3.1 this的不同應(yīng)用場(chǎng)景瑟俭,如何取值翎卓?

見(jiàn)2.3.1

3.2 手寫(xiě)bind函數(shù)

<pre class="prettyprint hljs javascript" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; word-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px;">Function.prototype.myBind = function () {
// 將參數(shù)拆解為數(shù)組
const args = Array.prototype.slice.call(arguments)
// 獲取this(args數(shù)組第一項(xiàng))
const t = args.shift()
// fn1.bind(...)中的fn1
const self = this
// 返回一個(gè)函數(shù)
return function () {
return self.apply(t, args)
}
}
function fn1(a, b, c) {
console.log('this ', this)
console.log(a, b, c)
console.log('this is fn1')
}
const fn2 = fn1.myBind({ x: 100 }, 1, 2, 3)
fn2()
復(fù)制代碼</pre>

3.3 實(shí)際開(kāi)發(fā)中閉包的應(yīng)用場(chǎng)景,舉例說(shuō)明

  • 隱藏?cái)?shù)據(jù)

<pre class="prettyprint hljs sql" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; word-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px;">// 閉包隱藏?cái)?shù)據(jù)摆寄,做一個(gè)簡(jiǎn)單的cache工具失暴,只提供API
function createCache() {
const data = {}
return {
set: function (key ,val) {
data[key] = val
},
get: function (key, val) {
return data[key]
}
}
}
const c = createCache()
c.set('a', 100)
console.log(c.get('a'))
復(fù)制代碼</pre>

3.4 創(chuàng)建10個(gè)a標(biāo)簽,點(diǎn)擊的時(shí)候彈出來(lái)對(duì)應(yīng)的序號(hào)

<pre class="prettyprint hljs javascript" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; word-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px;">// i是全局變量微饥,a的點(diǎn)擊事件發(fā)生時(shí)逗扒,i的值已經(jīng)變?yōu)?0
// let i, a
// for (i = 0; i < 10; i++) {
// a = document.createElement('a')
// a.innerHTML = i + '
'
// a.addEventListener('click', function(e){
// e.preventDefault()
// alert(i) // 10
// })
// document.body.appendChild(a)
// }

// 修改定義i的位置,構(gòu)成塊級(jí)作用域
let a
for (let i = 0; i < 10; i++) {
a = document.createElement('a')
a.innerHTML = i + '
'
a.addEventListener('click', function(e){
e.preventDefault()
alert(i) // 10
})
document.body.appendChild(a)
}
復(fù)制代碼</pre>

異步

一欠橘、題目

1.1 同步和異步的區(qū)別是什么缴阎?

1.2 手寫(xiě)用Promise加載一張圖片

1.3 前端使用異步的場(chǎng)景有哪些?

1.4 說(shuō)出以下的打印順序

<pre class="prettyprint hljs javascript" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; word-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px;">// setTimeout 筆試題
console.log(1)
setTimeout(function() {
console.log(2)
}, 1000)
console.log(3)
setTimeout(function() {
console.log(4)
}, 0)
console.log(5)
復(fù)制代碼</pre>

二简软、知識(shí)點(diǎn)

2.1 單線程和異步

  • JS是單線程語(yǔ)言,只能同時(shí)做一件事
  • 瀏覽器和nodejs已支持JS啟動(dòng)進(jìn)程述暂,如Web Worker
  • JS和DOM渲染共用同一個(gè)線程痹升,因?yàn)镴S可修改DOM結(jié)構(gòu)
  • 遇到等待(網(wǎng)絡(luò)請(qǐng)求,定時(shí)任務(wù))不能卡住
  • 因此畦韭,需要異步(為了解決單線程可能發(fā)生等待的問(wèn)題)
  • 異步基于回調(diào)callback函數(shù)形式

<pre class="prettyprint hljs javascript" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; word-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px;">// 異步 (callback 回調(diào)函數(shù))
console.log(100)
setTimeout(() => {
console.log(200)
}, 1000)
console.log(300)

// 同步
console.log(100)
alert(200)
console.log(300)
復(fù)制代碼</pre>

異步和同步

  • 基于JS是單線程語(yǔ)言
  • 異步不會(huì)阻塞代碼執(zhí)行
  • 同步會(huì)阻塞代碼執(zhí)行

2.2 異步的應(yīng)用場(chǎng)景

  • 網(wǎng)絡(luò)請(qǐng)求疼蛾,如ajax,圖片加載

<pre class="prettyprint hljs javascript" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; word-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px;">// ajax
console.log('start')
$.get('./data1.json', function(data1) {
console.log(data1)
})
console.log('end')

// 圖片加載
console.log('start')
let img = document.createElement('img')
img.onload = function () {
console.log('loaded')
}
img.src = '/xxx.png'
console.log('end')
復(fù)制代碼</pre>

  • 定時(shí)任務(wù)艺配,如setTimeout

<pre class="prettyprint hljs javascript" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; word-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px;">// setTimeout
console.log(100)
setTimeout(() => {
console.log(200)
}, 1000)
console.log(300)

// setIntelval
console.log(100)
setIntelval(() => {
console.log(200)
}, 1000)
console.log(300)
復(fù)制代碼</pre>

2.3 callback hell和Promise

callback hell 回調(diào)地獄

<pre class="prettyprint hljs typescript" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; word-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px;">// 獲取第一份數(shù)據(jù)
$.get(url1, (data1) => {
console.log(data1)

// 獲取第二份數(shù)據(jù)
$.get(url2, (data2) => {
console.log(data2)

  // 獲取第三份數(shù)據(jù)
$.get(url3, (data3) => {
  console.log(data3)

  // 還可能獲取更多數(shù)據(jù)
})

})
})
復(fù)制代碼</pre>

Promise解決回調(diào)地獄

<pre class="prettyprint hljs javascript" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; word-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px;">function getData(url) {
return new Promise((resolve, reject) => {
$.ajax({
url,
success(data) {
resolve(data)
},
error(err) {
reject(err)
}
})
})
}
getData(url1).then(data1 => {
console.log(data1)
return getData(url2)
}).then(data2 => {
console.log(data2)
return getData(url3)
}).then(data3 => {
console.log(data3)
}).catch(err => console.error(err))
復(fù)制代碼</pre>

三察郁、題目解答

3.1 同步和異步的區(qū)別是什么衍慎?

  • 基于JS是單線程語(yǔ)言
  • 異步不會(huì)阻塞代碼執(zhí)行
  • 同步會(huì)阻塞代碼執(zhí)行

3.2 手寫(xiě)用Promise加載一張圖片

<pre class="prettyprint hljs javascript" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; word-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px;">function loadImg(url) {
return new Promise((resolve, reject) => {
const image = new Image();
image.onload = () => {
resolve(image);
};
image.onerror = () => {
reject(new Error('圖片加載失敗:' + url));
};
image.src = url;
});
}
const url = '*'
loadImg(url).then(img => {
console.log(img.width)
}).catch(e => {
console.log(e)
})

const url1 = ''
const url2 = '
*'
loadImg(url1).then(img1 => {
console.log(img1.width)
return img1 // 普通對(duì)象
}).then(img1 => {
console.log(img1.height)
return loadImg(url2) // Promise 實(shí)例
}).then(img2 => {
console.log(img2.width)
return img2
}).then(img2 => {
console.log(img2.height)
}).catch(e => {
console.log(e)
})
復(fù)制代碼</pre>

3.3 前端使用異步的場(chǎng)景有哪些皮钠?

  • 網(wǎng)絡(luò)請(qǐng)求稳捆,如ajax,圖片加載
  • 定時(shí)任務(wù)麦轰,如setTimeout

3.4 說(shuō)出以下的打印順序

1 3 5 4 2

<pre class="prettyprint hljs javascript" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; word-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px;">// setTimeout 筆試題
console.log(1)
setTimeout(function() {
console.log(2)
}, 1000)
console.log(3)
setTimeout(function() {
console.log(4)
}, 0)
console.log(5)
復(fù)制代碼</pre>

JS Web API:DOM操作

DOM(Document Object Model)文檔對(duì)象模型

一乔夯、題目

1.1 DOM是哪種數(shù)據(jù)結(jié)構(gòu)

1.2 DOM操作的常用API

1.3 attr和property的區(qū)別

1.4 一次性插入多個(gè)DOM節(jié)點(diǎn),考慮性能

二款侵、知識(shí)點(diǎn)

2.1 DOM本質(zhì)

本質(zhì)上是一棵樹(shù)

<pre class="prettyprint hljs xml" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; word-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<div>
<p>this is p</p>
</div>
</body>
</html>

復(fù)制代碼</pre>

2.2 DOM節(jié)點(diǎn)操作

2.2.1 獲取DOM節(jié)點(diǎn)

<pre class="prettyprint hljs dart" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; word-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px;">const div1 = document.getElementById('div1') // 元素
const divList = document.getElementsByTagName('div') // 集合
const containerList = document.getElementsByClassName('container') // 集合
const pList = document.querySelectorAll('p') // 集合
復(fù)制代碼</pre>

2.2.2 attribute

<pre class="prettyprint hljs javascript" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; word-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px;">const pList = document.querySelectorAll('p')
const p = pList[0]
p.setAttribute('data-name', 'type')
console.log(p.getAttribute('data-name'))

p.setAttribute('style', 'color: red;')
console.log(p.getAttribute('style'))
復(fù)制代碼</pre>

2.2.3 property

JS通過(guò)property這種形式末荐,修改頁(yè)面的DOM渲染結(jié)構(gòu)

<pre class="prettyprint hljs javascript" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; word-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px;">const pList = document.querySelectorAll('p')
const p = pList[0]
p.style.width = '100px'
p.className = 'red-text'
console.log(p.nodeName) // P
console.log(p.nodeType) // 1
復(fù)制代碼</pre>

  • attribute:
    • 是HTML標(biāo)簽上的某個(gè)屬性,如id、class新锈、value等以及自定義屬性甲脏。
    • 它的值只能是字符串
    • 關(guān)于這個(gè)屬性一共有三個(gè)相關(guān)的方法,setAttribute妹笆、getAttribute块请、removeAttribute;
    • 修改HTML屬性晾浴,會(huì)改變HTML結(jié)構(gòu)
  • property:
    • 是js獲取的DOM對(duì)象上的屬性值负乡,比如a,你可以將它看作為一個(gè)基本的js對(duì)象脊凰。
    • 這個(gè)節(jié)點(diǎn)包括很多property抖棘,比如value,className以及一些方法onclik等方法狸涌。
    • 修改對(duì)象屬性切省,不會(huì)體現(xiàn)到HTML結(jié)構(gòu)中

以上兩者都有可能引起DOM重新渲染

2.3 DOM結(jié)構(gòu)操作

2.3.1 新增/插入節(jié)點(diǎn)

<pre class="prettyprint hljs xml" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; word-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<div id="div1" style="border-bottom: 1px solid red;">
<p id="p1">this is p1</p>
<p>this is p2</p>
<p>this is p3</p>
</div>
<div id="div2">
<p>this is p in div2</p>
</div>
<script> const div1 = document.getElementById('div1')
const div2 = document.getElementById('div2')

// 新建節(jié)點(diǎn)
const newP = document.createElement('p')
newP.innerHTML = 'this is new p'

// 插入節(jié)點(diǎn)
div1.appendChild(newP)

// 移動(dòng)節(jié)點(diǎn)
const p1 = document.getElementById('p1')
div2.appendChild(p1) </script>
</body>
</html>

復(fù)制代碼</pre>

2.3.2 獲取子元素列表,獲取父元素

<pre class="prettyprint hljs javascript" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; word-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px;">// 獲取父元素
console.log(p1.parentNode)
// 獲取子元素列表
const div1ChildeNodes = div1.childNodes
console.log('div1ChildeNodes: ', div1ChildeNodes)
const div1ChildeNodesP = Array.prototype.slice.call(div1ChildeNodes).filter(item => item.nodeType === 1) // 文本節(jié)點(diǎn)的nodeType === 3
console.log('div1ChildNodesP: ', div1ChildeNodesP)
復(fù)制代碼</pre>

2.3.3 刪除子元素

<pre class="prettyprint hljs less" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; word-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px;">// 刪除子元素節(jié)點(diǎn)
div1.removeChild(div1ChildeNodesP[0])
復(fù)制代碼</pre>

2.4 DOM性能

DOM操作非撑恋ǎ‘昂貴’朝捆,避免頻繁的DOM操作:

2.4.1 對(duì)DOM查詢(xún)做緩存

<pre class="prettyprint hljs javascript" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; word-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px;">// 不緩存DOM查詢(xún)結(jié)果
for(let i = 0; i < document.getElementsByTagName('p').length; i++) {
// 每次循環(huán),都會(huì)計(jì)算length懒豹,頻繁進(jìn)行DOM操作
}

// 緩存DOM查詢(xún)結(jié)果
const pList = document.getElementsByTagName('p')
const length = pList.length
for(let i = 0; i < length; i++) {
// 緩存length芙盘,只進(jìn)行一次DOM查詢(xún)
}
復(fù)制代碼</pre>

2.4.2 將頻繁操作改為一次性操作

<pre class="prettyprint hljs javascript" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; word-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px;">const list = document.getElementById('list')

// 方法1:頻繁操作
for(let i = 0; i < 10; i++) {
const li = document.createElement('li')
li.innerHTML = list item ${i}
list.appendChild(li)
}

// 方法2:一次性操作
// 創(chuàng)建一個(gè)文檔片段,此時(shí)還沒(méi)有插入到DOM樹(shù)中
const frag = document.createDocumentFragment()
// li元素插入到文檔片段
for(let i = 10; i < 20; i++) {
const li = document.createElement('li')
li.innerHTML = list item ${i}
frag.appendChild(li)
}
// 都完成之后脸秽,再將文檔片段插入到DOM樹(shù)中
list.appendChild(frag)
復(fù)制代碼</pre>

三儒老、題目解答

3.1 DOM是哪種數(shù)據(jù)結(jié)構(gòu)

樹(shù)(DOM樹(shù))

3.2 DOM操作的常用API

  • DOM節(jié)點(diǎn)操作
  • DOM結(jié)構(gòu)操作
  • attribute和property

3.3 attr和property的區(qū)別

  • property:修改對(duì)象屬性,不會(huì)體現(xiàn)到HTML結(jié)構(gòu)中
  • attribute:修改HTML屬性记餐,會(huì)改變HTML結(jié)構(gòu)
  • 兩者都有可能引起DOM重新渲染

(優(yōu)先使用property)

3.4 一次性插入多個(gè)DOM節(jié)點(diǎn)驮樊,考慮性能

<pre class="prettyprint hljs javascript" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; word-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px;">const list = document.getElementById('list')
// 創(chuàng)建一個(gè)文檔片段,此時(shí)還沒(méi)有插入到DOM樹(shù)中
const frag = document.createDocumentFragment()
// li元素插入到文檔片段
for(let i = 10; i < 20; i++) {
const li = document.createElement('li')
li.innerHTML = list item ${i}
frag.appendChild(li)
}
// 都完成之后,再將文檔片段插入到DOM樹(shù)中
list.appendChild(frag)
復(fù)制代碼</pre>

JS-Web-API-BOM

一囚衔、題目

1.1 如何識(shí)別瀏覽器的類(lèi)型

1.2 分析拆解URL各部分

二挖腰、知識(shí)點(diǎn)

2.1 navigator

<pre class="prettyprint hljs javascript" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; word-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px;">const ua = navigator.userAgent
const isChrome = ua.indexOf('Chrome')
console.log(isChrome)
復(fù)制代碼</pre>

2.2 screen

<pre class="prettyprint hljs css" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; word-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px;">console.log(screen.width)
console.log(screen.height)
復(fù)制代碼</pre>

2.3 location

<pre class="prettyprint hljs awk" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; word-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px;">location.href
location.protocol // 'http:' 'https:'
location.host // location.hostname + location.port
location.pathname
location.search
location.hash
復(fù)制代碼</pre>

2.4 history

<pre class="hljs less" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 0.75em; font-size: 14px; line-height: 1.5em; word-break: break-all; word-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px;">history.back()
history.forward()
復(fù)制代碼</pre>

JS-Web-API-事件

一、題目

1.1 編寫(xiě)一個(gè)通用的事件監(jiān)聽(tīng)函數(shù)

1.2 描述事件冒泡的流程

1.3 無(wú)限下拉的圖片列表练湿,如何監(jiān)聽(tīng)每個(gè)圖片的點(diǎn)擊猴仑?

二、知識(shí)點(diǎn)

2.1 事件綁定

<pre class="prettyprint hljs dart" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; word-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px;">// 點(diǎn)擊事件
const btn = document.getElementById('btn1')
btn.addEventListener('click', event => {
console.log('clicked')
})
復(fù)制代碼</pre>

<pre class="prettyprint hljs xml" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; word-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px;">// 通用的綁定函數(shù)(簡(jiǎn)版
<body>
<a id="link1" >link</a>
<script>)
function bindEvent(elem, type, fn) {
elem.addEventListener(type, fn)
}
const a = document.getElementById('link1')
bindEvent(a, 'click', e => {
console.log(event.target) // 獲取觸發(fā)的元素
e.preventDefault() // 阻止默認(rèn)行為
alert('clicked')
}) </script>
</body>
復(fù)制代碼</pre>

<pre class="prettyprint hljs xml" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; word-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px;">// 通用的綁定函數(shù)(支持普通綁定和事件代理)
<body>
<a id="link1" >link</a>
<div id="div3">
<a href="#">a1</a>
<a href="#">a2</a>
<a href="#">a3</a>
<button>加載更多</button>
</div>
<script> function bindEvent(elem, type, selector, fn) {
if (fn == null) {
fn = selector
selector = null
}
elem.addEventListener(type , event => {
const target = event.target
if (selector) {
// 代理綁定
if (target.matches(selector)) {
fn.call(target, event)
}
} else {
// 普通綁定
fn.call(target, event)
}
})
}
const link1 = document.getElementById('link1')
bindEvent(link1, 'click', function(e) {
e.preventDefault() // 阻止默認(rèn)行為
console.log(this.innerHTML)
})
const div3 = document.getElementById('div3')
bindEvent(div3, 'click', 'a', function(event) {
event.preventDefault()
console.log(this.innerHTML)
}) </script>
</body>
復(fù)制代碼</pre>

2.2 事件冒泡

子元素身上的事件鞠鲜,會(huì)冒泡到父元素身上宁脊,可用event.stopPropagation() 阻止冒泡行為

<pre class="prettyprint hljs xml" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; word-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><body>
<div id="div1">
<p id="p1">激活</p>
<p id="p2">取消</p>
<p id="p3">取消</p>
<p id="p4">取消</p>
</div>
<div id="div2" style="border-top: 1px solid red;">
<p id="p5">取消</p>
<p id="p6">取消</p>
</div>
<script> function bindEvent(elem, type, fn) {
elem.addEventListener(type, fn)
}
const p1 = document.getElementById('p1')
const body = document.body
bindEvent(p1, 'click', event => {
event.stopPropagation() // 阻止冒泡
console.log('激活')
})
bindEvent(body, 'click', event => {
console.log('取消')
}) </script>
復(fù)制代碼</pre>

2.3 事件代理(事件委托)

針對(duì)瀑布流這種子元素個(gè)數(shù)很多,或者內(nèi)部結(jié)構(gòu)比較復(fù)雜的情況下贤姆,將本來(lái)加在子元素身上的事件榆苞,加在其父元素身上。事件代理的好處有:

  1. 代碼簡(jiǎn)潔霞捡,比如不用for循環(huán)為子元素添加事件坐漏,js新生成的子元素不用新為其添加事件
  2. 減少瀏覽器內(nèi)存占用(相對(duì)于只為一個(gè)父元素綁定監(jiān)聽(tīng)事件,為每個(gè)子元素都綁定監(jiān)聽(tīng)事件更耗費(fèi)內(nèi)存)

但是碧信,不要濫用

<pre class="prettyprint hljs xml" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; word-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><body>
<div id="div3">
<a href="#">a1</a>
<a href="#">a2</a>
<a href="#">a3</a>
<button>加載更多</button>
</div>
<script> function bindEvent(elem, type, fn) {
elem.addEventListener(type, fn)
}
const div3 = document.getElementById('div3')
bindEvent(div3, 'click', event => {
event.preventDefault()
const target = event.target
if (target.nodeName === 'A') {
console.log(target.innerHTML)
}
}) </script>
</body>
復(fù)制代碼</pre>

三赊琳、題目解答

3.1 編寫(xiě)一個(gè)通用的事件監(jiān)聽(tīng)函數(shù)

見(jiàn)2.1

3.2 描述事件冒泡的流程

基于DOM樹(shù)形結(jié)構(gòu),事件會(huì)順著觸發(fā)元素往上冒泡

應(yīng)用場(chǎng)景:代理

3.3 無(wú)限下拉的圖片列表砰碴,如何監(jiān)聽(tīng)每個(gè)圖片的點(diǎn)擊躏筏?

  1. 利用事件代理,
  2. 用e.target獲取觸發(fā)元素呈枉,
  3. 用matches來(lái)判斷觸發(fā)元素是否在限制的觸發(fā)條件內(nèi)

JS-Web-API-Ajax

一趁尼、題目

1.1 手寫(xiě)一個(gè)簡(jiǎn)易的ajax

1.2 跨域的常用實(shí)現(xiàn)方式

二、知識(shí)點(diǎn)

2.1 XMLHttpRequest

2.1.1 get請(qǐng)求

<pre class="prettyprint hljs javascript" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; word-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px;">// get 請(qǐng)求
const xhr = new XMLHttpRequest()
xhr.open('GET', '/data/test.json', true) // true 異步請(qǐng)求
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
console.log(JSON.parse(xhr.responseText))
} else {
console.log('其他情況:', xhr.status)
}
}
}
xhr.send(null)
復(fù)制代碼</pre>

2.1.2 POST請(qǐng)求

<pre class="prettyprint hljs javascript" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; word-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px;">// POST 請(qǐng)求
const xhr = new XMLHttpRequest()
xhr.open('POST', '/login', true)
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
console.log(JSON.parse(xhr.responseText))
} else {
console.log('其他情況:', xhr.status)
}
}
}
const postData = {
username: 'zhangsan',
password: 'xxx'
}
xhr.send(JSON.stringify(postData))
復(fù)制代碼</pre>

2.1.3 xhr.readyState

  • 0-(未初始化)還沒(méi)有調(diào)用send()方法
  • 1-(載入)已調(diào)用send()方法猖辫,正在發(fā)送請(qǐng)求
  • 2-(載入完成)send()方法執(zhí)行完成酥泞,已經(jīng)接收到全部響應(yīng)內(nèi)容
  • 3-(交互)正在解析響應(yīng)內(nèi)容
  • 4-(完成)響應(yīng)內(nèi)容解析完成,可以在客戶(hù)端調(diào)用

2.1.4 xhr.status

  • 2xx - 表示成功處理請(qǐng)求啃憎,如200
    • 200 請(qǐng)求成功芝囤,對(duì)GET和POST請(qǐng)求的應(yīng)答文檔跟在后面
  • 3xx - 需要重定向,瀏覽器直接跳轉(zhuǎn)辛萍,如301悯姊,302,304
    • 301 永久重定向贩毕,被請(qǐng)求的資源已永久移動(dòng)到新位置悯许,并且將來(lái)任何對(duì)此資源的引用都應(yīng)該使用本響應(yīng)返回的若干個(gè) URI 之一。
    • 302 臨時(shí)重定向耳幢,請(qǐng)求的資源被暫時(shí)的移動(dòng)到了由Location 頭部指定的 URL上。瀏覽器會(huì)重定向到這個(gè)URL
    • 304 未改變,說(shuō)明無(wú)需再次傳輸請(qǐng)求的內(nèi)容睛藻,也就是說(shuō)可以使用緩存的內(nèi)容
  • 4xx - 客戶(hù)端請(qǐng)求錯(cuò)誤启上,如400,403店印,404
    • 400 Bad Request冈在,響應(yīng)狀態(tài)碼表示由于語(yǔ)法無(wú)效,服務(wù)器無(wú)法理解該請(qǐng)求
    • 403 Forbidden按摘, 資源不可用包券,服務(wù)器理解客戶(hù)的請(qǐng)求,但拒絕處理它炫贤。通常由于服務(wù)器上文件或目錄的權(quán)限設(shè)置導(dǎo)致溅固。
    • 404 Not Found,請(qǐng)求失敗兰珍,請(qǐng)求所希望得到的資源未被在服務(wù)器上發(fā)現(xiàn)
  • 5xx - 服務(wù)器端錯(cuò)誤
    • 500 Internal Server Error侍郭,服務(wù)器遇到了不知道如何處理的情況。

2.2 跨域:同源策略掠河,跨域解決方案

2.2.1 同源策略

  1. ajax請(qǐng)求
  • ajax請(qǐng)求時(shí)亮元, 瀏覽器 要求當(dāng)前網(wǎng)頁(yè)和server必須同源(安全)
  • 同源:協(xié)議、域名唠摹、端口爆捞,三者必須一致。如下就不屬于同源:前端(http:///a.com:8080/),server( a.com/api/xxxx )
  1. 加載圖片勾拉、css煮甥、js
  • 可無(wú)視同源策略:

    <pre class="prettyprint hljs xml" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; word-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto;"><img src=跨域的圖片地址 />
    <link src=跨域的css地址 />
    <script src=跨域的js地址></script>
    復(fù)制代碼</pre>

  • 加載圖片幅骄、css表窘、js可無(wú)視同源策略,實(shí)現(xiàn)跨域螟蒸,它們可實(shí)現(xiàn)的功能有:

    <pre class="hljs xml" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 0.75em; font-size: 14px; line-height: 1.5em; word-break: break-all; word-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto;"><img />
    <link /> <script> <script> </pre>

2.2.2 跨域

  • 所有的跨域找默,都必須經(jīng)過(guò)server端的允許和配合
  • 未經(jīng)server端允許就實(shí)現(xiàn)跨域艇劫,說(shuō)明瀏覽器有漏洞,危險(xiǎn)信號(hào)

<pre class="prettyprint hljs less" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; word-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px;">// CORS - 服務(wù)器設(shè)置http header
//第二個(gè)參數(shù)填寫(xiě)允許跨域的域名稱(chēng)惩激,不建議直接寫(xiě)'*'
response.setHeader('Access-Control-Allow-Origin', 'http://localhost:8011');
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');
復(fù)制代碼</pre>

2.2.3 JSONP

訪問(wèn)https://imooc.com店煞,服務(wù)端一定返回一個(gè)html文件嗎?- 不是的风钻,服務(wù)器可以任意動(dòng)態(tài)拼接數(shù)據(jù)返回顷蟀,只要符合html格式要求。同理于 <script src="https://imooc.com/getData.js"></script>

<script> 可繞過(guò)跨域限制骡技,服務(wù)器可以任意動(dòng)態(tài)拼接數(shù)據(jù)返回鸣个。所以羞反, <script> 就可以獲得跨域的數(shù)據(jù),只要服務(wù)端愿意返回

JSONP的實(shí)現(xiàn)原理:創(chuàng)建一個(gè)回調(diào)函數(shù)囤萤,然后在遠(yuǎn)程服務(wù)上調(diào)用這個(gè)函數(shù)并且將JSON 數(shù)據(jù)形式作為參數(shù)傳遞昼窗,完成回調(diào)。

<pre class="prettyprint hljs xml" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; word-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px;">// 前端jsonp.html
<script> window.callback = function(data) {
console.log(data)
} </script>
<script src='http://127.0.0.1:5501/jsonp.js'></script>

// 服務(wù)jsonp.js
callback(
{ name: 'zhangsan' }
)
復(fù)制代碼</pre>

三涛舍、題目解答

3.1 手寫(xiě)一個(gè)簡(jiǎn)易的ajax

<pre class="prettyprint hljs javascript" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; word-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px;">function ajax(url) {
const p = new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest()
xhr.open('GET', url, true)
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
resolve(JSON.parse(xhr.responseText))
} else {
reject('其他情況' + xhr.status)
}
}
}
xhr.send(null)
})
return p
}
ajax('/data/test.json').then(res => {
console.log(res)
}).catch(err => {
console.log(err)
})
復(fù)制代碼</pre>

3.2 跨域的常用實(shí)現(xiàn)方式

  1. JSONP
  2. CORS

JS-Web-API 存儲(chǔ)

一澄惊、題目

1.1 描述cookie、localStorage富雅、sessionStorage的區(qū)別

二掸驱、知識(shí)點(diǎn)

2.1 cookie

<pre class="hljs dart" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 0.75em; font-size: 14px; line-height: 1.5em; word-break: break-all; word-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px;">document.cookie = 'val=xxxxx'
</pre>

cookie的缺點(diǎn):

<pre class="hljs dart" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 0.75em; font-size: 14px; line-height: 1.5em; word-break: break-all; word-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px;">document.cookie = '***'
</pre>

2.2 localStorage、sessionStorage

  • HTML5專(zhuān)門(mén)為存儲(chǔ)而設(shè)計(jì)没佑,最大可存5M(針對(duì)每個(gè)域名)
  • API簡(jiǎn)單易用 setItem getItem
  • 不會(huì)隨著http請(qǐng)求被發(fā)送出去

localStorage毕贼、sessionStorage的區(qū)別:

  1. localStorage數(shù)據(jù)會(huì)永久存儲(chǔ),除非代碼或手動(dòng)刪除
  2. sessionStorage數(shù)據(jù)只存在于當(dāng)前會(huì)話图筹,瀏覽器關(guān)閉則清空
  3. 一般用localStorage會(huì)更多一些

三帅刀、題目解答

3.1 描述cookie、localStorage远剩、sessionStorage的區(qū)別

  1. 容量
  2. API易用性
  3. 是否會(huì)跟隨http請(qǐng)求發(fā)送出去

開(kāi)發(fā)環(huán)境

一扣溺、Git

  • 最常用的代碼版本管理工具
  • 大型項(xiàng)目需要多人協(xié)作開(kāi)發(fā),必須熟用git
  • Mac OS自帶git命令瓜晤,windows可去官網(wǎng)下載安裝
  • git服務(wù)端常見(jiàn)的有:github,coding.net等

1.1 常用git命令

git命令 作用
git init 在目錄中創(chuàng)建新的 Git 倉(cāng)庫(kù)
git clone [url] 拷貝一個(gè) Git
git add index.html hello.js 將文件添加到緩存
git add . 將所有文件添加到緩存
git status 查看在上次提交之后是否有修改
git diff 查看執(zhí)行 git status 的結(jié)果的詳細(xì)信息
git commit -m "提交注釋" 將緩存區(qū)內(nèi)容添加到倉(cāng)庫(kù)中
git branch [branchname] 創(chuàng)建分支
git checkout [branchname] 切換到需要修改的分支
git checkout -b [branchname] 創(chuàng)建新分支并立即切換到該分支下
git log 查看提交歷史
git push origin master 上傳代碼至遠(yuǎn)程倉(cāng)庫(kù)
git pull origin master 從遠(yuǎn)程倉(cāng)庫(kù)下載代碼病快速合并
git fetch 從遠(yuǎn)程倉(cāng)庫(kù)下載新分支與數(shù)據(jù)锥余,但不會(huì)自動(dòng)merge
git merge 遠(yuǎn)端倉(cāng)庫(kù)提取數(shù)據(jù)并嘗試合并到當(dāng)前分支

二、Chrome調(diào)試工具

image

2.1 Elements

dom結(jié)構(gòu)

2.2 Console

打印日志窗口

2.3 debugger

代碼中在需設(shè)置斷點(diǎn)處的地址加上 debugger 痢掠,或在Sources對(duì)應(yīng)的js文件添加斷點(diǎn)(點(diǎn)擊左側(cè)代碼行序號(hào))驱犹,則可以觸發(fā)斷點(diǎn)調(diào)試

2.4 Network

所有資源加載

2.5 Application

查看和操作本地存儲(chǔ)信息

三、抓包

移動(dòng)端H5頁(yè)足画,查看網(wǎng)絡(luò)請(qǐng)求雄驹,需要用工具抓包:

  • windows一般用fiddler
  • Mac OS一般用charles

抓包過(guò)程:

  1. 手機(jī)和電腦連同一個(gè)局域網(wǎng)
  2. 將手機(jī)代理到電腦上
  3. 手機(jī)瀏覽網(wǎng)頁(yè),即可抓包

四淹辞、webpack babel

  • ES6模塊化医舆,瀏覽器暫不支持
  • ES6語(yǔ)法,瀏覽器并不完全支持
  • 壓縮代碼象缀,整合代碼蔬将,以讓網(wǎng)頁(yè)加載更快

五、Linux常用命令

linux命令 作用
ls 查看所有文件
ls -a 查看所有文件央星,包括隱藏文件(-a 是all的意思)
ll 查看所有文件列表
clear 清屏
mkdir [name] 創(chuàng)建文件夾
rm -rf [name] 刪除文件夾及文件夾內(nèi)部所有內(nèi)容(-r遞歸霞怀,-f強(qiáng)制)
rm [name] 刪除文件
cd [name] 進(jìn)入文件夾
mv [oldName] [newName] 修改文件名稱(chēng)
mv index.html ../index.html 移動(dòng)文件存放路徑
cp index.html index1.html 復(fù)制文件
cat [name] 將該文件的所有內(nèi)容顯示在控制臺(tái)中
grep "關(guān)鍵字" [name] 在文件中查找關(guān)鍵字
touch [name] 新建文件
vi [name] 若無(wú)該文件則新建文件并進(jìn)入vim編輯器模式,若有該文件則直接打開(kāi)進(jìn)入vim
進(jìn)入vim編輯器模式莉给,輸入i毙石,即可編輯輸入 -
點(diǎn)擊esc退出編輯模式廉沮,再輸入:wq,即可保存并退出vim模式 -
若輸入后徐矩,不想保存废封,則輸入:q!,即可強(qiáng)制退出 -

運(yùn)行環(huán)境

  • 運(yùn)行環(huán)境即瀏覽器(server端有nodejs)
  • 下載網(wǎng)頁(yè)代碼丧蘸,渲染出頁(yè)面,期間會(huì)執(zhí)行若干JS
  • 要保證代碼在瀏覽器中穩(wěn)定且高效

一遥皂、網(wǎng)頁(yè)加載過(guò)程

1.1 題目

1.1.1 從輸入U(xiǎn)RL到渲染出頁(yè)面的整個(gè)過(guò)程

1.1.2 window.onload和DOMContentLoaded的區(qū)別

1.2 知識(shí)點(diǎn)

1.2.1 加載資源的形式

  • HTML代碼
  • 媒體文件力喷,如圖片、視頻等
  • javascript css

1.2.2 加載資源的過(guò)程

  1. DNS解析:域名 -> IP地址
  2. 瀏覽器根據(jù)IP地址向服務(wù)器發(fā)起http請(qǐng)求
  3. 服務(wù)器處理http請(qǐng)求演训,并返回給瀏覽器

1.2.3 渲染頁(yè)面的過(guò)程

  1. 根據(jù)HTML代碼生成 DOM Tree

  2. 根據(jù)CSS代碼生成CSSOM(object model)

  3. 將DOM Tree和CSSOM整合形成Render Tree

  4. 根據(jù)Render Tree渲染頁(yè)面

  5. 遇到 <script> 則暫停渲染弟孟,優(yōu)先加載并執(zhí)行JS代碼,完成再繼續(xù)

  6. 直至把Render Tree渲染完成

思考

為什么把CSS放在head標(biāo)簽中样悟?

  1. css放在body標(biāo)簽尾部時(shí), DOMTree構(gòu)建完成之后便開(kāi)始構(gòu)建RenderTree, 并計(jì)算布局渲染網(wǎng)頁(yè), 等加載解析完css之后, 開(kāi)始構(gòu)建CSSOMTree, 并和DOMTree重新構(gòu)建RenderTree, 重新計(jì)算布局渲染網(wǎng)頁(yè)
  2. css放在head標(biāo)簽中時(shí), 先加載并解析css拂募,構(gòu)建CSSOMTree, 與此同時(shí)構(gòu)建DOMTree, CSSOMTree和DOMTree都構(gòu)建完畢之后開(kāi)始構(gòu)建RenderTree, 計(jì)算布局渲染網(wǎng)頁(yè)

對(duì)比兩者, css放在head標(biāo)簽中比css放在body標(biāo)簽尾部少了一次構(gòu)建RenderTree, 一次計(jì)算布局和一次渲染網(wǎng)頁(yè), 因此性能會(huì)更好; 并且css放在body標(biāo)簽尾部時(shí)會(huì)在網(wǎng)頁(yè)中短暫出現(xiàn)"裸奔"的HTML, 這不利于用戶(hù)體驗(yàn)

為何建議把js放在body最后?

  1. 避免JavaScript操作DOM失效
  2. 在解析JavaScript代碼之前窟她,將頁(yè)面的內(nèi)容完全呈現(xiàn)在瀏覽器中陈症,用戶(hù)會(huì)因?yàn)闉g覽器顯示空白頁(yè)面的時(shí)間縮短而感到打開(kāi)頁(yè)面的速度變快了

<pre class="hljs xquery" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 0.75em; font-size: 14px; line-height: 1.5em; word-break: break-all; word-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px;">window.onload和DOMContentLoaded
</pre>

<pre class="prettyprint hljs javascript" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; word-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px;">window.addEventListener('load', function() {
// 頁(yè)面的全部資源加載完才會(huì)執(zhí)行,包括圖片震糖、視頻等
})
window.addEventListener('DOMContentLoaded', function() {
// DOM渲染完即可執(zhí)行录肯,此時(shí)圖片、視頻還可能沒(méi)加載完
})
復(fù)制代碼</pre>

1.3 題目

1.3.1 從輸入U(xiǎn)RL到渲染出頁(yè)面的整個(gè)過(guò)程

  • 下載資源:各個(gè)資源類(lèi)型吊说,下載過(guò)程
  • 渲染頁(yè)面:結(jié)合html css javascript 圖片等

1.3.2 window.onload和DOMContentLoaded的區(qū)別

  • window.onload資源全部加載完成后才能執(zhí)行论咏,包括圖片
  • DOMContentLoaded DOM渲染完成即可,圖片可能尚未下載

二颁井、性能優(yōu)化

2.1 性能優(yōu)化原則

  • 多使用內(nèi)存厅贪、緩存或其他方法
  • 減少CPU計(jì)算量,減少網(wǎng)絡(luò)加載耗時(shí)

2.2 從何入手

2.2.1 讓加載更快

  1. 減少資源體積:

    • 壓縮代碼
  2. 減少訪問(wèn)次數(shù):

    • 合并代碼(webpack合并js css文件雅宾、雪碧圖)

    <pre class="prettyprint hljs xml" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; word-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto;"><script src="a.js"></script>
    <script src="b.js"></script>
    <script src="c.js"></script>

    <script src="abc.js"></script>
    復(fù)制代碼</pre>

    • SSR服務(wù)端渲染
      1. 服務(wù)端渲染:將網(wǎng)頁(yè)和數(shù)據(jù)一起加載养涮,一起渲染
      2. 非SSR:先加載網(wǎng)頁(yè),再加載數(shù)據(jù)秀又,再渲染數(shù)據(jù)
    • 緩存
      1. 靜態(tài)資源加hash后綴单寂,根據(jù)文件內(nèi)容計(jì)算hash
      2. 文件內(nèi)容不變,則hash不變吐辙,則URL不變
      3. URL和文件不變宣决,則會(huì)自動(dòng)觸發(fā)http緩存機(jī)制,返回304
  3. 使用更快的網(wǎng)絡(luò):CDN(根據(jù)地域做靜態(tài)服務(wù))

2.2.2 讓渲染更快

  1. CSS 放在head昏苏,JS放在body最下面
  2. 盡早開(kāi)始執(zhí)行JS尊沸,用DOMContentLoaded觸發(fā)
  3. 懶加載(圖片懶加載威沫,上滑加載更多)
  4. 對(duì)DOM查詢(xún)進(jìn)行緩存
  5. 頻繁DOM操作,合并到一起再插入到DOM結(jié)構(gòu)
  6. 節(jié)流 防抖

2.2.3 防抖 debounce

含義:當(dāng)持續(xù)觸發(fā)事件時(shí)洼专,一定時(shí)間段內(nèi)沒(méi)有再觸發(fā)事件棒掠,事件處理函數(shù)才會(huì)執(zhí)行一次,如果設(shè)定的時(shí)間到來(lái)之前屁商,又一次觸發(fā)了事件烟很,就重新開(kāi)始延時(shí)

<pre class="prettyprint hljs javascript" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; word-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px;">function debounce (fn, delay = 500) {
let timer = null
return function () {
if (timer) {
clearTimeout(timer)
}
timer = setTimeout(() => {
fn.apply(this, arguments)
timer = null
}, delay)
}
}
const input1 = document.getElementById('input1')
input1.addEventListener('keyup', debounce(function(e) {
console.log(e.target)
console.log(this.value)
}, 1000))
復(fù)制代碼</pre>

2.2.4 節(jié)流

含義:當(dāng)持續(xù)觸發(fā)事件時(shí),保證一定時(shí)間段內(nèi)只調(diào)用一次事件處理函數(shù)蜡镶。節(jié)流通俗解釋就比如我們水龍頭放水雾袱,閥門(mén)一打開(kāi),水嘩嘩的往下流官还,秉著勤儉節(jié)約的優(yōu)良傳統(tǒng)美德芹橡,我們要把水龍頭關(guān)小點(diǎn),最好是如我們心意按照一定規(guī)律在某個(gè)時(shí)間間隔內(nèi)一滴一滴的往下滴望伦。

<pre class="prettyprint hljs xml" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; word-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px;">/**

  • 拖拽一個(gè)元素時(shí)林说,要隨時(shí)拿到該元素被拖拽的位置
  • 直接用drag事件,則會(huì)頻繁觸發(fā)屯伞,很容易導(dǎo)致卡頓
  • 節(jié)流:無(wú)論拖拽速度多快腿箩,都會(huì)每隔100ms觸發(fā)一次
    */
    <body>
    <div id="div1" draggable="true" style="width: 100px;height: 100px;border: 1px solid red;">可拖拽</div>
    <script> // 節(jié)流
    function throttle(fn, delay = 100) {
    let timer = null
    return function () {
    if (timer) {
    return
    }
    timer = setTimeout(() => {
    fn.apply(this, arguments)
    timer = null
    }, delay)
    }
    }
    const div1 = document.getElementById('div1')
    div1.addEventListener('drag' , throttle(function(e) {
    console.log(e.offsetX, e.offsetY)
    }, 500)) </script>
    </body>
    復(fù)制代碼</pre>

三、安全

3.1 常見(jiàn)的web前端攻擊方式有哪些

3.1.1 XSS跨站請(qǐng)求攻擊

攻擊情景模擬:

<pre class="hljs xml" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 0.75em; font-size: 14px; line-height: 1.5em; word-break: break-all; word-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><script> </pre>

XSS攻擊預(yù)防:

  1. 替換特殊字符劣摇,如 < 變?yōu)?&lt; > 變?yōu)?&gt;
  2. <script> 變?yōu)?&lt;script&gt; 度秘,將會(huì)作為字符串直接顯示,而不會(huì)作為腳本執(zhí)行(npm 有一個(gè)xss工具包可幫忙替換: www.npmjs.com/package/xss…
  3. 前端要替換饵撑,后端也要替換

3.1.2 CSRF跨站請(qǐng)求偽造

攻擊情景模擬:

  1. 銀行網(wǎng)站A剑梳,它以GET請(qǐng)求來(lái)完成銀行轉(zhuǎn)賬的操作,如: www.mybank.com/Transfer.ph…
  2. 危險(xiǎn)網(wǎng)站B滑潘,它里面有一段HTML的代碼如下:

<pre class="prettyprint hljs xml" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; word-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px;">?<img src=http://www.mybank.com/Transfer.php?toBankId=11&money=1000>
復(fù)制代碼</pre>

  1. 首先垢乙,你登錄了銀行網(wǎng)站A,然后訪問(wèn)危險(xiǎn)網(wǎng)站B语卤,噢追逮,這時(shí)你會(huì)發(fā)現(xiàn)你的銀行賬戶(hù)少了1000塊......

為什么會(huì)這樣呢?原因是銀行網(wǎng)站A違反了HTTP規(guī)范粹舵,使用GET請(qǐng)求更新資源钮孵。在訪問(wèn)危險(xiǎn)網(wǎng)站B的之前,你已經(jīng)登錄了銀行網(wǎng)站A眼滤,而B(niǎo)中的 <img> 以GET的方式請(qǐng)求第三方資源(這里的第三方就是指銀行網(wǎng)站了巴席,原本這是一個(gè)合法的請(qǐng)求,但這里被不法分子利用了)诅需,所以你的瀏覽器會(huì)帶上你的銀行網(wǎng)站A的Cookie發(fā)出Get請(qǐng)求漾唉,去獲取資源“ www.mybank.com/Transfer.ph…荧库,結(jié)果銀行網(wǎng)站服務(wù)器收到請(qǐng)求后,認(rèn)為這是一個(gè)更新資源操作(轉(zhuǎn)賬操作)赵刑,所以就立刻進(jìn)行轉(zhuǎn)賬操作.

CSRF攻擊預(yù)防:

  1. 使用POST接口
  2. 增加驗(yàn)證分衫,例如密碼、短信驗(yàn)證碼般此、指紋等

需要更多學(xué)習(xí)資料的同學(xué)可以加Q群:1093606290

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末蚪战,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子铐懊,更是在濱河造成了極大的恐慌屎勘,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,277評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件居扒,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡丑慎,警方通過(guò)查閱死者的電腦和手機(jī)喜喂,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)竿裂,“玉大人玉吁,你說(shuō)我怎么就攤上這事∧逡欤” “怎么了进副?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,624評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)悔常。 經(jīng)常有香客問(wèn)我影斑,道長(zhǎng),這世上最難降的妖魔是什么机打? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,356評(píng)論 1 293
  • 正文 為了忘掉前任矫户,我火速辦了婚禮,結(jié)果婚禮上残邀,老公的妹妹穿的比我還像新娘皆辽。我一直安慰自己,他們只是感情好芥挣,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,402評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布驱闷。 她就那樣靜靜地躺著,像睡著了一般空免。 火紅的嫁衣襯著肌膚如雪空另。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,292評(píng)論 1 301
  • 那天蹋砚,我揣著相機(jī)與錄音痹换,去河邊找鬼征字。 笑死,一個(gè)胖子當(dāng)著我的面吹牛娇豫,可吹牛的內(nèi)容都是我干的匙姜。 我是一名探鬼主播,決...
    沈念sama閱讀 40,135評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼冯痢,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼氮昧!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起浦楣,我...
    開(kāi)封第一講書(shū)人閱讀 38,992評(píng)論 0 275
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤袖肥,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后振劳,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體椎组,經(jīng)...
    沈念sama閱讀 45,429評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,636評(píng)論 3 334
  • 正文 我和宋清朗相戀三年历恐,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了寸癌。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,785評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡弱贼,死狀恐怖蒸苇,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情吮旅,我是刑警寧澤溪烤,帶...
    沈念sama閱讀 35,492評(píng)論 5 345
  • 正文 年R本政府宣布,位于F島的核電站庇勃,受9級(jí)特大地震影響檬嘀,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜责嚷,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,092評(píng)論 3 328
  • 文/蒙蒙 一枪眉、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧再层,春花似錦贸铜、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,723評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至蛋济,卻和暖如春棍鳖,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,858評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工渡处, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留镜悉,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,891評(píng)論 2 370
  • 正文 我出身青樓医瘫,卻偏偏與公主長(zhǎng)得像侣肄,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子醇份,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,713評(píng)論 2 354