声明:慕课网《前端JavaScript面试技巧》的笔记,仅用于查阅复习,不得用于商业用途。html
基础知识前端
JS APInode
开发环境jquery
运行环境面试
关于面试ajax
关于基础算法
先从几道面试题提及json
typeof
能获得的哪些类型?===
什么时候使用==
?window.onload
和DOMContentLoaded
的区别?<a>
标签,点击的时候弹出来对应的序号模块加载器
,实现相似require.js
的基本功能随机排序
思考数组
看到的是什么
?永远也看不完
的题海?如何搞定全部面试题浏览器
上一节思考问题的结论
看到的是什么
? -> 考点
永远也看不完
的题海? -> 不变应万变
题目到知识再到题目
题目考察的知识点
typeof
能获得的哪些类型?JS变量类型
===
什么时候使用==
?强制类型转换
window.onload
和DOMContentLoaded
的区别?浏览器渲染过程
<a>
标签,点击的时候弹出来对应的序号做用域
模块加载器
,实现相似require.js
的基本功能JS模块化
随机排序
JS基础算法
变量类型和计算
题目
知识点
变量类型
值类型
let a = 100
let b = a
a = 200
console.log(b) // 100
复制代码
引用类型
let a = { age: 20 }
let b = a
b.age = 21
console.log(a.age) // 21
复制代码
typeof运算符
typeof undefined // "undefined"
typeof 'abc' // "string"
typeof 123 // "number"
typeof true // "boolean"
typeof {} // "object"
typeof [] // "object"
typeof null // "object"
typeof console.log // "function"
复制代码
变量计算 - 强制类型转换
字符串拼接
let a = 100 + 10 // 110
let b = 100 + '10' // "10010"
复制代码
==运算符
100 == '100' // true
0 == '' // true
null == undefined // true
复制代码
if语句
let a = true
if (a) {
// ...
}
let b = 100
if (b) {
// ...
}
let c = ''
if (c) {
// ...
}
复制代码
逻辑运算符
console.log(10 && 0) // 0
console.log('' || 'abc') // "abc"
console.log(!window.abc) // true
// 判断一个变量会被当作true仍是false
let a = 100
console.log(!!a) // true
复制代码
解答
JS中使用typeof能获得的类型
symbol
let sym = Symbol('commet')
console.log(typeof sym) // "symbol"
复制代码
什么时候使用===什么时候使用==
if (obj.a == null) {
// 这里至关于obj.a === null || obj.a === undefined,简写形式
// 这是jquery源码中推荐的写法
}
复制代码
JS中的内置函数
String
Number
Boolean
Object
Array
Function
Data
RegExp
Error
复制代码
JS按存储方式区分变量类型
如何理解JSON
JSON.stringify({ a: 10, b: 20 )
JSON.parse('{"a":10,"b":20}')
复制代码
if (...) {}中false的状况:false 0 NaN null undefined
内置对象有:JSON、Math
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
复制代码
原型和原型链
题目
数组类型
知识点
构造函数
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) // 建立多个对象
复制代码
构造函数-扩展
判断一个变量是否为“数组”:变量 instanceof Array
原型规则和示例
原型规则
是学习原型链
的基础5条原型规则
__proto__
(隐式原型)属性,属性值是一个普通的对象prototype
(显示原型)属性,属性值也是一个普通的对象__proto__
属性值指向它的构造函数的prototype
属性值__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()
复制代码
for (let item in f) {
// 高级浏览器已经在 for in 中屏蔽了来自原型的属性
// 可是这里建议你们仍是加上这个判断,保证程序的健壮性
if (f.hasOwnProperty(item)) {
console.log(item)
}
}
复制代码
// 构造函数
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__中查找
复制代码
原型链
instanceof
引用类型
属于哪一个构造函数
的方法解题
如何准确判断一个变量是数组类型
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一个对象的过程
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(或其余框架)源码中如何使用原型链
写一个封装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')
})
复制代码
做用域和闭包
题目
<a>
标签,点击的时候弹出来对应的序号知识点
执行上下文
console.log(a) // undefined
var a = 100
fn('lilei') // "lilei" 20
function fn(name) {
age = 20
console.log(name, age)
var age
}
复制代码
<script>
或者一个函数PS:注意“函数声明”和“函数表达式”的区别
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
// 构造函数
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}
复制代码
做用域
// 无块级做用域
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()
复制代码
// js 没有块级做用域
// ES6 有块级做用域
复制代码
闭包
function F1() {
var a = 100
// 返回一个函数(函数做为返回值)
return function() {
console.log(a)
}
}
// f1 获得一个函数
var f1 = F1()
var a = 200
f1() // 100
复制代码
闭包的使用场景
// 闭包 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
复制代码
解题
<a>
标签,点击的时候弹出来对应的序号说一下对变量提高的理解
说明this几种不一样的使用场景
建立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的值
复制代码
异步和单线程
题目
知识点
什么是异步
console.log(100)
setTimeout(function() {
console.log(200)
}, 1000)
console.log(300)
复制代码
同步阻塞后续程序代码执行,异步不会阻塞程序的的运行。
对比同步
console.log(100)
alert(200) // 1秒钟以后手动点击确认
console.log(300)
复制代码
什么时候须要异步
前端使用异步的场景
<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')
复制代码
异步和单线程
console.log(100)
setTimeout(function() {
console.log(200)
})
console.log(300)
复制代码
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')
复制代码
同步和异步的区别是什么
一个关于setTimeout的笔试题
console.log(1)
setTimeout(function() {
console.log(2)
}, 0)
console.log(3)
setTimeout(function() {
console.log(4)
}, 1000)
console.log(5)
复制代码
前端使用异步的场景有哪些
重点总结
其余知识
题目
知识点
日期
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
数组API
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])
}
}
复制代码
解答
获取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)
})
复制代码
重点总结
从基础只是到JS-Web-API
回顾JS基础知识
JS-Web-API
W3C标准中关于JS的规定有:
页面弹框是window.alert(123),浏览器须要作:
获取元素document.getElementById(id),浏览器须要:
可是W3C标准没有规定任何JS基础相关的东西
全面考虑,JS内置的全局函数和对象有哪些?
总结
常说的JS(浏览器执行的JS)包含两部分:
DOM操做(Document Object Model)
题目:
知识点:
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代码就是一个字符串,可是浏览器已经把字符串结构化成树形结构了。
DOM能够理解为:
DOM节点操做
获取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;')
复制代码