【面試】前端JavaScript面試技巧(更新中...)

聲明:慕課網《前端JavaScript面試技巧》的筆記,僅用於查閱複習,不得用於商業用途。html

第1章 課程簡介

1-1 課程簡介

基礎知識前端

  • 原型 原型鏈
  • 做用域 閉包
  • 異步 單線程

JS APInode

  • DOM操做
  • Ajax
  • 事件綁定

開發環境jquery

  • 版本管理
  • 模塊化
  • 打包工具

運行環境面試

  • 頁面渲染
  • 性能優化

1-2 前言

  • 關於面試
  • 關於基礎

關於面試ajax

  • 基層工程師 - 基礎知識
  • 高級工程師 - 項目經驗
  • 架構師 - 解決方案

關於基礎算法

  • 工程師的自我修養 - 基礎
  • 紮實的基礎會讓你高效學習新技術

1-3 幾個面試題

先從幾道面試題提及json

  • JS中使用typeof能獲得的哪些類型?
  • 什麼時候使用===什麼時候使用==
  • window.onloadDOMContentLoaded的區別?
  • 用JS建立10個<a>標籤,點擊的時候彈出來對應的序號
  • 簡述如何實現一個模塊加載器,實現相似require.js的基本功能
  • 實現數組的隨機排序

思考數組

  • 拿到一個面試題,你第一時間看到的是什麼
  • 又如何看待網上搜出來的永遠也看不完的題海?
  • 如何對待接下來遇到的面試題?

1-4 如何搞定全部面試題

如何搞定全部面試題瀏覽器

  • 上一節思考問題的結論
  • 題目考察的知識點

上一節思考問題的結論

  • 拿到一個面試題,你第一時間看到的是什麼? -> 考點
  • 又如何看待網上搜出來的永遠也看不完的題海? -> 不變應萬變
  • 如何對待接下來遇到的面試題? -> 題目到知識再到題目

題目考察的知識點

  • JS中使用typeof能獲得的哪些類型?
  • 考點:JS變量類型
  • 什麼時候使用===什麼時候使用==
  • 考點:強制類型轉換
  • window.onloadDOMContentLoaded的區別?
  • 考點:瀏覽器渲染過程
  • 用JS建立10個<a>標籤,點擊的時候彈出來對應的序號
  • 考點:做用域
  • 簡述如何實現一個模塊加載器,實現相似require.js的基本功能
  • 考點:JS模塊化
  • 實現數組的隨機排序
  • 考點:JS基礎算法

JS基礎知識(上)

2-1 變量類型和計算-1

變量類型和計算

  • 題目
  • 知識點
  • 解答

題目

  • JS中使用typeof能獲得的哪些類型
  • 什麼時候使用===什麼時候使用==
  • JS中有哪些內置函數
  • JS變量按照存儲方式區分爲哪些類型,並描述其特色
  • 如何理解JSON

知識點

  • 變量類型
  • 變量計算

變量類型

  • 值類型 vs 引用類型
  • typeof運算符

值類型

let a = 100
let b = a
a = 200
console.log(b) // 100
複製代碼

引用類型

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

typeof運算符

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

變量計算 - 強制類型轉換

  • 字符串拼接
  • ==運算符
  • if語句
  • 邏輯運算

字符串拼接

let a = 100 + 10 // 110
let b = 100 + '10' // "10010"
複製代碼

==運算符

100 == '100' // true
0 == '' // true
null == undefined // true
複製代碼

if語句

let a = true
if (a) {
    // ...
}
let b = 100
if (b) {
    // ...
}
let c = ''
if (c) {
    // ...
}
複製代碼

邏輯運算符

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

// 判斷一個變量會被當作true仍是false
let a = 100
console.log(!!a) // true
複製代碼

2-2 變量類型和計算-2

解答

JS中使用typeof能獲得的類型

  • 問題:JS中使用typeof能獲得的哪些類型
  • 答案:undefined、string、number、boolean、object、function、symbol
let sym = Symbol('commet')
console.log(typeof sym) // "symbol"
複製代碼

什麼時候使用===什麼時候使用==

  • 問題:什麼時候使用===什麼時候使用==
  • 答案:判斷對象的某個屬性是否存在或爲null時可使用==,由於jquery源碼這麼使用
if (obj.a == null) {
    // 這裏至關於obj.a === null || obj.a === undefined,簡寫形式
    // 這是jquery源碼中推薦的寫法
}
複製代碼

JS中的內置函數

  • 問題:JS中有哪些內置函數 —— 數據封裝類對象
  • 答案:
String
Number
Boolean
Object
Array
Function
Data
RegExp
Error
複製代碼

JS按存儲方式區分變量類型

  • 問題:JS變量按照存儲方式區分爲哪些類型,並描述其特色
  • 答案:值類型 和 引用類型

2-3 變量類型和計算-3 如何理解JSON

如何理解JSON

  • 問題:如何理解JSON
  • 答案:JSON只不過是一個JS對象而已,也是一種數據格式
JSON.stringify({ a: 10, b: 20 )
JSON.parse('{"a":10,"b":20}')
複製代碼

2-4 變量類型和計算-3 代碼演示

if (...) {}中false的狀況:false 0 NaN null undefined

內置對象有:JSON、Math

2-5 typeof symbol 【ES6變量類型】

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

2-6 原型和原型鏈

原型和原型鏈

  • 題目
  • 知識點
  • 解答

題目

  • 如何準確判斷一個變量是數組類型
  • 寫一個原型鏈繼承的例子
  • 描述new一個對象的過程
  • zepto(或其餘框架)源碼中如何使用原型鏈

知識點

  • 構造函數
  • 構造函數 - 擴展
  • 原型規則和示例
  • 原型鏈
  • instanceof

構造函數

function Foo(name, age) {
    this.name = name
    this.age = age
    this.class = 'class-1'
    // return this // 默認有這一行
}
let f = new Foo('lilei', 18)
// let f2 = new Foo('hanmeimei', 17) // 建立多個對象
複製代碼

構造函數-擴展

  • let a = {} 實際上是let a = new Object()的語法糖
  • let a = [] 實際上是let a = new Array()的語法糖
  • function Foo(){...} 實際上是let Foo = new Function(...)
  • 使用instanceof判斷一個函數是不是一個變量的構造函數

判斷一個變量是否爲「數組」:變量 instanceof Array

2-7 原型和原型鏈-5個原型規則

原型規則和示例

  • 5條原型規則
  • 原型規則是學習原型鏈的基礎

5條原型規則

  1. 全部的引用類型(數組、對象、函數),都具備對象特性,便可自由擴展屬性(除了"null"之外)
  2. 全部的引用類型(數組、對象、函數),都有一個__proto__(隱式原型)屬性,屬性值是一個普通的對象
  3. 全部的函數,都有一個prototype(顯示原型)屬性,屬性值也是一個普通的對象
  4. 全部的引用類型(數組、對象、函數),__proto__屬性值指向它的構造函數的prototype屬性值
  5. 當試圖獲得一個對象的某個屬性時,若是這個對象自己沒有這個屬性,那麼會去它的__proto__(即它的構造函數的prototype)中尋找
let obj = {}
obj.a = 100
let arr = []
arr.a = 100
function fn() {}
fn.a = 100

console.log(obj.__proto__)
console.log(arr.__proto__)
console.log(fn.__proto__)

console.log(fn.prototype)

console.log(obj.__proto__ === Object.prototype)
複製代碼
// 構造函數
function Foo(name, age) {
    this.name = name
}
Foo.prototype.alertName = function() {
    alert(this.name)
}

// 建立實例
let f = new Foo('lilei')
f.printName = function() {
    console.log(this.name)
}
// 測試
f.printName()
f.alertName()
複製代碼

2-8 原型和原型鏈-5個原型規則-補充二點

for (let item in f) {
    // 高級瀏覽器已經在 for in 中屏蔽了來自原型的屬性
    // 可是這裏建議你們仍是加上這個判斷,保證程序的健壯性
    if (f.hasOwnProperty(item)) {
        console.log(item)
    }
}
複製代碼

2-9 原型和原型鏈-原型鏈

// 構造函數
function Foo(name, age) {
    this.name = name
}
Foo.prototype.alertName = function() {
    alert(this.name)
}

// 建立實例
let f = new Foo('lilei')
f.printName = function() {
    console.log(this.name)
}
// 測試
f.printName()
f.alertName()
f.toString() // 要去f.__proto__.__proto__中查找
複製代碼

原型鏈

原型鏈

2-10 原型和原型鏈-原型鏈-instanceof

instanceof

  • 用於判斷引用類型屬於哪一個構造函數的方法
  • f instanceof Foo 的判斷邏輯是:
  • f的__proto__一層一層往上,可否對應到Foo.prototype
  • 再試着判斷f instanceof Object

2-11 原型和原型鏈-解答1

解題

  • 如何準確判斷一個變量是數組類型
  • 寫一個原型鏈繼承的例子
  • 描述new一個對象的過程
  • zepto(或其餘框架)源碼中如何使用原型鏈

如何準確判斷一個變量是數組類型

let arr = []
arr instanceof Array // true
typeof arr // object,typeof是沒法判斷是不是數組的
複製代碼

寫一個原型鏈繼承的例子

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

// 接下來代碼演示時,會推薦更加貼近實戰的原型繼承示例
複製代碼

描述new一個對象的過程

  • 建立一個新對象
  • this指向這個新對象
  • 執行代碼,即對this賦值
  • 返回this
function Foo(name, age) {
    this.name = name
    this.age = age
    this.class = 'class-1'
    // return this // 默認有這一行
}

let f = new Foo('lilei', 18)
// let f2 = new Foo('hanmeimei', 18) // 建立多個對象
複製代碼

zepto(或其餘框架)源碼中如何使用原型鏈

  • 閱讀源碼是高效提升技巧的方式
  • 但不能「埋頭苦鑽」有技巧在其中
  • 慕課網搜索「zepto設計和源碼分析」

2-12 原型和原型鏈-解答2-些一個貼近實際開發原型鏈繼承的例子

寫一個封裝DOM查詢的例子

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

Elem.prototype.html = function(val) {
  let elem = this.elem
  if (val) {
    elem.innerHTML = val
    return this // 爲了鏈式操做
  } else {
    return elem.innerHTML
  }
}

Elem.prototype.on = function(type, fn) {
  let elem = this.elem
  elem.addEventListener(type, fn)
}

let div1 = new Elem('div1')
// console.log(div1.html())
div1.html('<p>hello imooc</p>').on('click', function() {
  alert('clicked')
})
複製代碼

2-13 原型和原型鏈-代碼演示

第3章 JS基礎知識(中)

3-1 做用域和閉包-執行上下文

做用域和閉包

  • 題目
  • 知識點
  • 解答

題目

  • 說一下對變量提高的理解
  • 說明this幾種不一樣的使用場景
  • 建立10個<a>標籤,點擊的時候彈出來對應的序號
  • 如何理解做用域
  • 實際開發中閉包的應用

知識點

  • 執行上下文
  • this
  • 做用域
  • 做用域鏈
  • 閉包

執行上下文

console.log(a) // undefined
var a = 100

fn('lilei') // "lilei" 20
function fn(name) {
    age = 20
    console.log(name, age)
    var age
}
複製代碼
  • 範圍:一段<script>或者一個函數
  • 全局:變量定義、函數聲明
  • 函數:變量定義、函數聲明、this、arguments

PS:注意「函數聲明」和「函數表達式」的區別

3-2 做用域和閉包-執行上下文-代碼演示

3-3 做用域和閉包-this

this

  • this要在執行時才能確認值,定義時沒法確認
var a = {
    name: 'A',
    fn: function() {
        console.log(this.name)
    }
}
a.fn() // this === a
a.fn.call({ name: 'B' }) // this爲{ name: 'B' }
var fn1 = a.fn
fn1() // this === window
複製代碼

this

  • 做爲構造函數執行
  • 做爲對象屬性執行
  • 做爲普通函數執行
  • call apply bind

3-4 做用域和閉包-this-代碼演示

// 構造函數
function Foo(name) {
    this.name = name
}
let f = new Foo('lilei')
f.name // "lilei"
複製代碼
// 做爲一個對象的屬性
let obj = {
    name: 'A',
    printName: function() {
        console.log(this.name)
    }
}
obj.printName() // "A"
複製代碼
// 普通函數
function fn() {
    console.log(this)
}
fn() // window
複製代碼
// call apply bind
function fn1(name, age) {
    console.log(name)
    console.log(this)
}
fn1.call({ x: 1 }, 'lilei', 20) // "lilei" {x: 1}
fn1.apply({ x: 200 }, ['lilei', 20]) // "lilei" {x: 200}

let fn2 = function(name, age) {
    console.log(name)
    console.log(this)
}.bind({x: 300})
fn2('lilei', 20) // "lilei" {x: 300}
複製代碼

3-5 做用域和閉包-做用域

做用域

  • 沒有塊級做用域
  • 只有函數和全局做用域
// 無塊級做用域
if (true) {
    var name = 'lilei'
}
console.log(name) // "lilei"

// 函數和全局做用域
var a = 100
function fn() {
    var a = 200
    console.log('fn', a)
}
console.log('global', a) // "global 100"
fn() // "fn 200"
複製代碼

做用域鏈

var a = 100
function fn() {
    var b = 200
    // 當前做用域沒有定義的變量,即「自由變量」
    console.log(a)
    console.log(b)
}
fn()
複製代碼
var a = 100
function F1() {
    var b = 200
    function F2() {
        var c = 300
        console.log(a) // a 是自由變量
        console.log(b) // b 是自由變量
        console.log(c)
    }
    F2()
}
F1()
複製代碼

3-6 做用域和閉包-做用域-代碼演示

3-7 補充-ES6塊級做用域

// js 沒有塊級做用域
// ES6 有塊級做用域
複製代碼

3-8 做用域和閉包-閉包

閉包

function F1() {
    var a = 100
    
    // 返回一個函數(函數做爲返回值)
    return function() {
        console.log(a)
    }
}
// f1 獲得一個函數
var f1 = F1()
var a = 200
f1() // 100
複製代碼

閉包的使用場景

  • 函數做爲返回值(上一個demo)
  • 函數做爲參數傳遞(本身思考)

3-9 做用域和閉包-閉包-代碼演示

// 閉包 1,函數做爲返回值
function F1() {
    var a = 100
    return function() {
        console.log(a) // a 自由變量,向父做用域去尋找 ——函數**定義**時的父做用域
    }
}
var f1 = F1()
var a = 200
f1() // 100
複製代碼
// 閉包 2,函數做爲參數傳遞
function F1() {
    var a = 100
    return function() {
        console.log(a)
    }
}
var f1 = F1()
function F2(fn) {
    var a = 300
    fn()
}
F2(f1) // 100
複製代碼

3-10 做用域和閉包-解題

解題

  • 說一下對變量提高的理解
  • 說明this幾種不一樣的使用場景
  • 建立10個<a>標籤,點擊的時候彈出來對應的序號
  • 如何理解做用域
  • 實際開發中閉包的應用

說一下對變量提高的理解

  • 變量定義
  • 函數聲明(注意和函數表達式的區別)

說明this幾種不一樣的使用場景

  • 做爲構造函數執行
  • 做爲對象屬性執行
  • 做爲普通函數執行
  • call apply bind

建立10個<a>標籤 點擊的時候彈出來對應的序號

// 這是一個錯誤的寫法!!!
var i, a
for (i = 0; i < 10; i++) {
    a = document.createElement('a')
    a.innerHTML = i + '<br>'
    a.addEventListener('click', function(e) {
        e.preventDefault()
        alert(i) // 自由變量,要去父做用域獲取值
    })
    document.body.appendChild(a)
}
複製代碼
// 這是正確的寫法!!!
var i
for (i = 0; i < 100; i++) {
    (function(i) {
        var a = document.createElement('a')
        a.innerHTML = i + '<br>'
        a.addEventListener('click', function(e) {
            e.preventDefault()
            alert(i)
        })
        document.body.appendChild(a)
    })(i)
}
複製代碼

如何理解做用域

  • 自由變量
  • 做用域鏈,即自由變量的查找
  • 閉包的兩個場景

實際開發中閉包的應用

// 閉包實際應用中主要用於封裝變量,收斂權限
function isFirstLoad() {
    var _list = []
    return function(id) {
        if (_list.indexOf(id) >= 0) {
            return false
        } else {
            _list.push(id)
            return true
        }
    }
}

// 使用
var firstLoad = isFirstLoad()
firstLoad(10) // true
firstLoad(10) // false
firstLoad(20) // true
// 你在isFirstLoad函數外,根本不可能修改掉_list的值
複製代碼

3-11 做用域和閉包-解題-代碼演示

第4章JS基礎知識(下)

4-1 異步和單線程-什麼是異步

異步和單線程

  • 題目
  • 知識點
  • 解答

題目

  • 同步和異步的區別是什麼?分別舉一個同步和異步的例子
  • 一個關於setTimeout的筆試題
  • 前端使用異步的場景有哪些

知識點

  • 什麼是異步(對比同步)
  • 前端使用異步的場景
  • 異步和單線程

什麼是異步

console.log(100)
setTimeout(function() {
    console.log(200)
}, 1000)
console.log(300)
複製代碼

同步阻塞後續程序代碼執行,異步不會阻塞程序的的運行。

對比同步

console.log(100)
alert(200) // 1秒鐘以後手動點擊確認
console.log(300)
複製代碼

什麼時候須要異步

  • 在可能發生等待的狀況
  • 等待過程當中不能像alert同樣阻塞程序運行
  • 所以,全部的"等待的狀況"都須要異步

前端使用異步的場景

  • 定時任務:setTimeout, setInterval
  • 網絡請求:ajax請求, 動態<img>加載
  • 事件綁定

ajax請求代碼示例

console.log('start')
$.get('./data1.json', function(data1) {
    console.log(data1)
})
console.log('end')
複製代碼

<img>加載示例

console.log('start')
var img = document.createElement('img')
img.onload = function() {
    console.log('loaded')
}
img.src = '/xxx.png'
console.log('end')
複製代碼

事件綁定示例

console.log('start')
document.getElementById('btn1').addEventListener('click', function() {
    alert('clicked')
})
console.log('edn')
複製代碼

4-2 異步和單線程-什麼是異步-代碼演示

4-3 異步和單線程-單線程

異步和單線程

console.log(100)
setTimeout(function() {
    console.log(200)
})
console.log(300)
複製代碼
  • 執行第一行,打印100
  • 執行setTimeout後,傳入setTimeout的函數會被暫存起來,不會當即執行(單線程的特色,不能同時幹兩件事)
  • 執行最後一行,打印300
  • 待全部程序執行完,處於空閒狀態時,會立馬看有沒有暫存起來的要執行
  • 發現暫存起來的setTimeout中的函數無需等待時間,就當即過來執行
console.log('start')
$.get('./data1.json', function(data1) {
    console.log(data1)
})
console.log('end')
複製代碼
console.log('start')
document.getElementById('btn1').addEventListener('click', function() {
    alert('clicked')
})
console.log('edn')
複製代碼
  • js是單線程語言,即一次只能幹一件事,若是同時有兩件事,另外一件就先上一邊排隊去,我先幹完這件再說,若是沒有異步,那就會出現阻塞現象
  • 因爲js是單線程,在代碼執行的時候又不能由於執行須要等待的代碼而形成阻塞,所以js會首先將無需等待的(同步)代碼執行完成後,來處理異步代碼,若是達到異步代碼的執行條件的話,就會執行

4-4 異步和單線程-解答

  • 同步和異步的區別是什麼?分別舉一個同步和異步的例子
  • 一個關於setTimeout的筆試題
  • 前端使用異步的場景有哪些

同步和異步的區別是什麼

  • 同步會阻塞代碼執行,而異步不會
  • alert是同步,setTimeout是異步

一個關於setTimeout的筆試題

console.log(1)
setTimeout(function() {
    console.log(2)
}, 0)
console.log(3)
setTimeout(function() {
    console.log(4)
}, 1000)
console.log(5)
複製代碼

前端使用異步的場景有哪些

  • 定時任務:setTimeout、setInterval
  • 網絡請求:ajax請求、動態加載
  • 事件綁定

重點總結

  • 異步和同步的區別
  • 異步和單線程的關係
  • 異步在前端的引用場景

4-5 其餘知識點-日期和Math

其餘知識

  • 題目
  • 知識點
  • 解答

題目

  • 獲取2017-06-10格式的日期
  • 獲取隨機數,要求是長度一致的字符串格式
  • 寫一個能遍歷對象和數組的通用forEach函數

知識點

  • 日期
  • Math
  • 數組API
  • 對象API

日期

Date.now() // 獲取當前時間毫秒數
var dt = new Date()
dt.getTime() // 獲取毫秒數
dt.getFullYear() // 年
dt.getMonth() // 月(0-11)
dt.getDate() // 日(0-31)
dt.getHours() // 小時(0-23)
dt.getMinutes() // 分鐘(0-59)
dt.getSeconds() // 秒(0-59)
複製代碼

Math

  • 獲取隨機數Math.random()

4-6 其餘知識點-數組和對象的API

數組API

  • forEach 遍歷全部元素
  • every 判斷全部元素是否都符合條件
  • some 判斷是否有至少一個元素符合條件
  • sort 排序
  • map 對元素從新組裝,生成新數組
  • filter 過濾符合條件的元素

forEach

var arr = [1, 2, 3]
arr.forEach(function(item, index) {
    // 遍歷數組的全部元素
    console.log(index, item)
})
複製代碼

every

var arr = [1, 2, 3]
var result = arr.every(function(item, index) {
    // 用來判斷全部的數組元素,都知足條件
    if (item < 4) {
        return true
    }
})
console.log(result)
複製代碼

some

var arr = [1, 2, 3]
var result = arr.every(function(item, index) {
    // 用來判斷只要有一個數組元素,知足條件
    if (item < 2) {
        return true
    }
})
console.log(result)
複製代碼

sort

var arr = [1, 4, 2, 3, 5]
var arr2 = arr.sort(function(a, b) {
    // 從小到大排序
    return a - b
    
    // 從大到小排序
    return b - a
})
console.log(arr2)
複製代碼

map

var arr = [1, 2, 3, 4]
var arr2 = arr.map(function(item, index) {
    // 將元素從新組裝,並返回
    return '<b>' + item + '</b>'
})
console.log(arr2)
複製代碼

filter

var arr = [1, 2, 3]
var arr2 = arr.filter(function(item, index) {
    // 經過某一個條件過濾數組
    if (item >= 2) {
        feturn true
    }
})
console.log(arr2)
複製代碼

對象API

var obj = {
    x: 100,
    y: 200,
    z: 300
}
var key
for (key in obj) {
    // 注意這裏的 hasOwnProperty,在講原型鏈的時候講過了
    if (obj.hasOwnProperty(key)) {
        console.log(key, obj[key])
    }
}
複製代碼

4-7 其餘知識點-知識點代碼演示

4-8 其餘知識點-解答

解答

  • 獲取2017-06-10格式的日期
  • 獲取隨機數,要求是長度一致的字符串格式
  • 寫一個能遍歷對象和數組的通用forEach函數

獲取2017-06-10格式的日期

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

獲取隨機數,要求是長度一致的字符串格式

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

寫一個能遍歷對象和數組的通用forEach函數

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

var arr = [1, 2, 3]
// 注意,這裏參數的順序換了,爲了和對象的遍歷格式一致
forEach(arr, function(index, item) {
    console.log(index, item)
})

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

重點總結

  • 日期
  • Math
  • 數組API
  • 對象API

4-9 其餘知識點-代碼演示

第5章 JS-Web-API(上)

5-1 從基礎只是到JSWebAPI

從基礎只是到JS-Web-API

  • 回顧JS基礎只是
  • JS-Web-API
  • 總結

回顧JS基礎知識

  • 變量類型和計算
  • 原型和原型鏈
  • 閉包和做用域
  • 異步和單線程
  • 其餘(如日期、Math、各類經常使用API)
  • 特色:表面看起來並不能用於工做中開發代碼
  • 內置函數:Object Array Boolean String ...
  • 內置對象:Math JSON ...
  • 咱們連在網頁彈出一句hello world都不能實現

JS-Web-API

  • JS基礎知識:ECMA262標準
  • JS-Web-API:W3C標準

W3C標準中關於JS的規定有:

  • DOM操做
  • BOM操做
  • 事件綁定
  • ajax請求(包括http協議)
  • 存儲

頁面彈框是window.alert(123),瀏覽器須要作:

  • 定義一個window全局變量,對象類型
  • 給他定義一個alert屬性,屬性值是一個函數

獲取元素document.getElementById(id),瀏覽器須要:

  • 定義一個document全局變量,對象類型
  • 給它定義一個getElementById的屬性,屬性值是一個函數

可是W3C標準沒有規定任何JS基礎相關的東西

  • 無論什麼變量類型、原型、做用域和異步
  • 只管定義用於瀏覽器中JS操做頁面的API和全局變量

全面考慮,JS內置的全局函數和對象有哪些?

  • 以前講過的Object Array Boolean String Math JSON 等
  • 剛剛提的window document
  • 接下來還有繼續講到的全部未定義的全局變量,如navigator.userAgent

總結

常說的JS(瀏覽器執行的JS)包含兩部分:

  • JS基礎知識(ECMA262標準)
  • JS-Web-API(W3C標準)

5-2 DOM本質

DOM操做(Document Object Model)

  • 題目
  • 知識點
  • 解答

題目:

  • DOM是哪一種基本的數據結構?
  • DOM操做的經常使用API有哪些?
  • DOM節點的attr和property有何區別?

知識點:

  • DOM本質
  • DOM節點操做
  • DOM結構操做

DOM的本質

<?xml version="1.0" encoding="utf-8"?>
<note>
    <to>Tove</to>
    <from>Jani</from>
    <heading>Reminder</heading>
    <body>Don't forget me this weekend!</body> <other> <a></a> <b></b> </other> </note> 複製代碼
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Document</title>
</head>
<body>
  <div>
    <p>this is p</p>
  </div>
</body>
</html>
複製代碼

DOM本質:瀏覽器拿到html代碼後,DOM把html代碼結構化成瀏覽器可識別以及js可識別的東西。

html代碼就是一個字符串,可是瀏覽器已經把字符串結構化成樹形結構了。

5-3 DOM節點操做

DOM能夠理解爲:

  • 瀏覽器把拿到的html代碼,結構化成一個瀏覽器能識別而且js可操做的一個模型而已。

DOM節點操做

  • 獲取DOM節點
  • Property
  • Attribute

獲取DOM節點

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

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

Property

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

// 獲取nodeName 和 nodeType
console.log(p.nodeName)
console.log(p.nodeType)
複製代碼

Attribute

var pList = document.querySelectorAll('p')
var p = pList[0]
p.getAttribute('data-name')
p.setAttribute('data-name', 'imooc')
p.getAttribute('style')
p.setAttribute('style', 'font-size: 30px;')
複製代碼
相關文章
相關標籤/搜索