- 值類(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>
(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>
- 引用類(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>
棧從上往下添加數(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>
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>
- 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>
- 邏輯判斷
<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>
原型關(guān)系:
- 每個(gè)class都有顯示原型prototype
- 每個(gè)實(shí)例都有隱式原型proto
- 實(shí)例的proto指向?qū)?yīng)class的prototype
基于原型的執(zhí)行規(guī)則
獲取屬性tom.name或執(zhí)行tom.sayHi()時(shí),
- 先在自身屬性和方法尋找
- 如果找不到則自動(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>
再看instanceof:
tom instanceof People
tom的隱式原型沿著原型鏈瘟滨,一路往上查找候醒,能否找到People的顯示原型,若能找到室奏,則返回 true
重要提示火焰!
- class是ES6語(yǔ)法規(guī)范,由ECMA委員會(huì)發(fā)布
- ECMA只規(guī)定語(yǔ)法規(guī)則胧沫,即我們代碼的書(shū)寫(xiě)規(guī)范昌简,不規(guī)定如何實(shí)現(xiàn)
- 以上實(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.get(0)
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 作用域和自由變量
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):
- 函數(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>
- 函數(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)加在子元素身上的事件榆苞,加在其父元素身上。事件代理的好處有:
- 代碼簡(jiǎn)潔霞捡,比如不用for循環(huán)為子元素添加事件坐漏,js新生成的子元素不用新為其添加事件
- 減少瀏覽器內(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)擊躏筏?
- 利用事件代理,
- 用e.target獲取觸發(fā)元素呈枉,
- 用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 同源策略
- ajax請(qǐng)求
- ajax請(qǐng)求時(shí)亮元, 瀏覽器 要求當(dāng)前網(wǎng)頁(yè)和server必須同源(安全)
- 同源:協(xié)議、域名唠摹、端口爆捞,三者必須一致。如下就不屬于同源:前端(http:///a.com:8080/),server( a.com/api/xxxx )
- 加載圖片勾拉、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)方式
- JSONP
- 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ū)別:
- localStorage數(shù)據(jù)會(huì)永久存儲(chǔ),除非代碼或手動(dòng)刪除
- sessionStorage數(shù)據(jù)只存在于當(dāng)前會(huì)話图筹,瀏覽器關(guān)閉則清空
- 一般用localStorage會(huì)更多一些
三帅刀、題目解答
3.1 描述cookie、localStorage远剩、sessionStorage的區(qū)別
- 容量
- API易用性
- 是否會(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)試工具
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ò)程:
- 手機(jī)和電腦連同一個(gè)局域網(wǎng)
- 將手機(jī)代理到電腦上
- 手機(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ò)程
- DNS解析:域名 -> IP地址
- 瀏覽器根據(jù)IP地址向服務(wù)器發(fā)起http請(qǐng)求
- 服務(wù)器處理http請(qǐng)求演训,并返回給瀏覽器
1.2.3 渲染頁(yè)面的過(guò)程
根據(jù)HTML代碼生成 DOM Tree
根據(jù)CSS代碼生成CSSOM(object model)
將DOM Tree和CSSOM整合形成Render Tree
根據(jù)Render Tree渲染頁(yè)面
遇到
<script>
則暫停渲染弟孟,優(yōu)先加載并執(zhí)行JS代碼,完成再繼續(xù)直至把Render Tree渲染完成
思考
為什么把CSS放在head標(biāo)簽中样悟?
- 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è)
- 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最后?
- 避免JavaScript操作DOM失效
- 在解析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 讓加載更快
-
減少資源體積:
- 壓縮代碼
-
減少訪問(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ù)端渲染
- 服務(wù)端渲染:將網(wǎng)頁(yè)和數(shù)據(jù)一起加載养涮,一起渲染
- 非SSR:先加載網(wǎng)頁(yè),再加載數(shù)據(jù)秀又,再渲染數(shù)據(jù)
- 緩存
- 靜態(tài)資源加hash后綴单寂,根據(jù)文件內(nèi)容計(jì)算hash
- 文件內(nèi)容不變,則hash不變吐辙,則URL不變
- URL和文件不變宣决,則會(huì)自動(dòng)觸發(fā)http緩存機(jī)制,返回304
使用更快的網(wǎng)絡(luò):CDN(根據(jù)地域做靜態(tài)服務(wù))
2.2.2 讓渲染更快
- CSS 放在head昏苏,JS放在body最下面
- 盡早開(kāi)始執(zhí)行JS尊沸,用DOMContentLoaded觸發(fā)
- 懶加載(圖片懶加載威沫,上滑加載更多)
- 對(duì)DOM查詢(xún)進(jìn)行緩存
- 頻繁DOM操作,合并到一起再插入到DOM結(jié)構(gòu)
- 節(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ù)防:
- 替換特殊字符劣摇,如
<
變?yōu)?<
>
變?yōu)?>
-
<script>
變?yōu)?<script>
度秘,將會(huì)作為字符串直接顯示,而不會(huì)作為腳本執(zhí)行(npm 有一個(gè)xss工具包可幫忙替換: www.npmjs.com/package/xss… - 前端要替換饵撑,后端也要替換
3.1.2 CSRF跨站請(qǐng)求偽造
攻擊情景模擬:
- 銀行網(wǎng)站A剑梳,它以GET請(qǐng)求來(lái)完成銀行轉(zhuǎn)賬的操作,如: www.mybank.com/Transfer.ph…
- 危險(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>
- 首先垢乙,你登錄了銀行網(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ù)防:
- 使用POST接口
- 增加驗(yàn)證分衫,例如密碼、短信驗(yàn)證碼般此、指紋等
需要更多學(xué)習(xí)資料的同學(xué)可以加Q群:1093606290