清空或截断数组
const arr = [11, 22, 33, 44, 55, 66];
// truncanting
arr.length = 3;
console.log(arr); // => [11, 22, 33]
//clearing
arr.length = 0;
console.log(arr); // => []
console.log(arr[2]); // => undefined
题目
解答
知识点
题目
解答
// 动物
function Animal() {
this.eat = function () {
console.log('animal eat')
}
}
// 狗
function Dog() {
this.bark = function () {
console.log('dog bark')
}
}
Dog.prototype = new Animal()
// 哈士奇
var hashiqi = new Dog()
// 接下来代码演示时,会推荐更加贴近实战的原型继承示例!
描述new 一个对象的过程
zepto (或其他框架) 源码中如何使用原型链
知识点
var obj = {}; obj.a = 100;
var 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);
}
// 创建示例
var f = new Foo('zhangsan')
f.printName = function () {
console.log(this.name);
}
// 测试
f.printName(); // zhangsan
f.alertName(); // zhangsan
var item;
for (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);
}
// 创建示例
var f = new Foo('zhangsan')
f.printName = function () {
console.log(this.name)
}
// 测试
f.printName()
f.alertName()
f.toString() // 要去 f.__proto__.__proto__中查找
instanceof
题目
// 这是一个错误的写法!!!
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 < 10; 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
知识点
console.log(a) // undefined
var a = 100
fn('zhangsan') // 'zhangsan' 20
function fn(name) {
age = 20
console.log(name, age)
var age
}
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
// 无块级作用域
if (true) {
var name = 'zhangsan'
}
console.log(name)
// 函数和全局作用域
var a = 100
function fn() {
var a = 200
console.log('fn', a)
}
console.log('global', a)
fn()
//作用域链
var a = 100
function fn() {
var b = 200
// 当前作用域没有定义的变量,即 "自由变量"
console.log(a)
console.log(b)
}
fn()
function F1() {
var a = 100
// 返回一个函数 (函数作为返回值)
return function () {
console.log(a)
}
}
// f1 得到一个函数
var f1 = F1()
var a = 200
f1()
题目
console.log(1)
setTimeout(function () {
console.log(2)
}, 0)
console.log(3)
setTimeout(function () {
console.log(4)
}, 1000)
console.log(5)
知识点
// 异步-不阻塞
console.log(100)
setTimeout(function() {
console.log(200)
}, 1000)
console.log(300)
// 同步-阻塞
console.log(100)
alert(200)
console.log(300)
// 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('end')
题目
function formatDate(dt) {
if (!dt) {
dt = new Date()
}
var year = dt.getFullYear()
var month = dt.getMonth() + 1
var date = dt.getDate()
if (month < 10) {
// 强制类型转换
month = '0' + month
}
if (date < 10) {
// 强制类型转换
date = '0' + date
}
// 强制类型转换
return year + '-' + month + '-' + date
}
var dt = new Date()
var formatDate = formatDate(dt)
console.log(formatDate)
var random = Math.random()
var random = random + '0000000000' // 后面加上10个零
var random = random.slice(0, 10)
console.log(random)
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)
})
知识点
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)
var arr = [1,2,3]
arr.forEach(function (item, index) {
// 遍历数组的所有元素
console.log(index, item)
})
var arr = [1,2,3]
var result = arr.every(function (item, index) {
// 用来判断所有的数组元素,都满足一个条件
if (item < 4) {
return true
}
})
console.log(result)
var arr = [1,2,3]
var result = arr.some(function (item, index) {
// 用来判断所有的数组元素,只要有一个满足条件即可
if (item < 2) {
return true
}
})
console.log(result)
var arr = [1,4,2,3,5]
var arr2 = arr.sort(function(a, b) {
// 从小到大排序
return a - b
// 从大到小排序
// return b - a
})
console.log(arr2)
var arr = [1,2,3,4]
var arr2 = arr.map(function(item, index) {
// 将元素重新组装,并返回
return '<b>' + item + '</b>'
})
console.log(arr2)
var arr = [1,2,3,4]
var arr2 = arr.filter(function(item, index) {
// 通过某一个条件过滤数组
if (item >= 2) {
return true
}
})
console.log(arr2)
var obj = {
x: 100,
y: 200,
z: 300
}
var key
for (key in obj) {
// 注意这里的 hasOwnProperty, 再讲原型链时候讲过了
if (obj.hasOwnProperty(key)) {
console.log(key, obj[key])
}
}
题目
知识点
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)
p.className = 'p1'
// 获取 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', 'sss')
p.getAttribute('style')
p.setAttribute('style', 'font-size:28px;')
// 新增节点
var div1 = document.getElementById('div1')
// 添加新节点
var p1 = document.createElement('p')
p1.innerHtml = 'this is p1'
div1.appendChild(p1) // 添加新创建元素
// 移动已有节点
var p2 = document.getElementById('p2')
div1.appendChild(p2)
// 获取父元素和子元素
var div1 = document.getElementById('div1')
var parent = div1.parentElement
var child = div1.childNodes
div1.removeChild(child[0])
题目
var ua = navigator.userAgent
var isChrome = ua.indexOf('Chrome')
console.log(isChrome)
location.href
location.protocol
location.pathname
location.search
location.hash
知识点
// navigator
var ua = navigator.userAgent
var isChrome = ua.indexOf('Chrome')
console.log(isChrome)
// screen
console.log(screen.width)
console.log(screen.height)
// location
console.log(location.href)
console.log(location.protocol) // 'http:' 'https:'
console.log(location.pathname) // user/api
console.log(location.search)
console.log(location.hash)
// history
history.back()
history.forward()
题目
知识点
var btn = document.getElementById('btn1')
btn.addEventListener('click', function (event) {
console.log('clicked')
})
function bindEvent(elem, type, fn) {
elem.addEventListener(type, fn)
}
var a = document.getElementById('link1')
bindEvent(a, 'click', function(e) {
e.preventDefault() // 阻止默认行为
alert('clicked')
})
var div1 = document.getElementById('div1')
div1.addEventListener('click', function(e) {
var target = e.target
if (target.nodeName === 'A') {
alert(target.innerHTML)
}
})
function bindEvent(elem, type, selector, fn) {
if (fn == null) {
fn = selector
selector = null
}
elem.addEventListener(type, function (e) {
var target
if (selector) {
target = e.target
if (target.matches(selector)) {
fn.call(target, e)
}
} else {
fn(e)
}
})
}
题目
知识点
var xhr = new XMLHttpRequest()
xhr.open("GET", "/api", false)
xhr.onreadystatechange = function () {
// 这里的函数异步执行,可参考之前JS基础中的异步模块
if (xhr.readyState == 4) {
if (xhr.status == 200) {
alert(xhr.responseText)
}
}
}
xhr.send(null)
题目
知识点
知识点
题目
知识点
答案
window.onload // 页面的全部资源加载完才会执行,包括图片、视频等
DOMContentLoaded // DOM渲染完即可执行,此时图片、视频还可能没有加载完
原则
从哪里入手
加载资源优化
渲染优化
//合并DOM插入
var listNode = document.getElementById('list')
// 要插入10个 li 标签
var frag = document.createDocumentFragment() // 不触发DOM操作
var x, li;
for (x = 0; x < 10; x++) {
li = document.createElement("li")
li.innerHTML = "list item " + x
frag.appendChild(li)
}
listNode.appendChild(frag) //触发DOM操作
var textarea = document.getElementById('text')
var timeoutId
textarea.addEventListener('keyup', function () {
if (timeoutId) {
clearTimeout(timeoutId)
}
timeoutId = setTimeout(function () {
// 触发 change 事件
}, 100)
})
知识点
预防
预防
事件轮巡
ES7提案
用法
问题
v-dom 是什么?
遇到的问题
问题
vdom为何使用diff算法
答案:
diff算法的实现过程
什么是diff算法?
{
tag: 'ul',
attrs: {
id: 'list'
},
children: [
{
tag: 'li',
attrs: {
className: 'item'
},
children: ['Item 1']
}
]
}
问题
题目
从jQuery到框架
如何理解 MVVM
什么是响应式
问题解答
模板是什么?
render 函数 - with的用法
var obj = {
name: 'zhangsan',
age: 20,
getAddress: function () {
alert('beijing')
}
}
function fn() {
with(obj){
console.log(name)
console.log(age)
getAddress()
}
}
解答
题目
组件的封装
组件的复用
解答
JSX语法
JSX 解析
JSX独立的标准
问题解答
为何需要vdom
React.createElement和h
自定义组件的解析
问题解答
setState的异步
addTitle(title) {
const currentList = this.state.list
console.log(this.state.list) // ['a', 'b']
this.setState({
list:currentList.concat(title) // 'c'
})
console.log(this.state.list) // ['a', 'b']
}
setState 为何需要异步?
vue修改属性也是异步
setState的过程
答案:
问题解答
前言
两者的本质区别
模板的区别
组件化的区别
两者共同点
问题解答
题目
hybrid 文字解释
hybrid存在价值
webview
file:// 协议
hrbrid 具体实现
实现
具体实现 - 遗留问题
问题解答
思考 (目的,可行途径)
完整流程
问题解答
优点
缺点
适用的场景
问题解答
之前遗留的问题
JS和客户端通讯的基本形式
/* 网上搜的微信的部分 schema 协议 */
weixin://dl/scan 扫一扫
weixin://dl/feedback 反馈
weixin://dl/moments 朋友圈
weixin://dl/settings 设置
内置上线
问题解答
看书 - 手下不离书
博客 - 合格程序员的必备
开源 - github 的 star 是硬通货