########## -> 目录 <- ##########
讲义内容概括
1 - 包括:
a - JavaScript 语法 【 初级 】
b - ES6 语法 【 初级 】
c - MVVM 框架讲解
d - VUE 原理讲解
e - VUE 语法 【 初级 】
f - VUE 脚手架 及 webpack 配置 【 基础 】
g - chrome 调试方法 【 初级 】
2 - 不包括:
a - HTML HTML5 语法
b - CSS CSS3 语法
c - CSS 拓展语言 【 less sass 】
d - 编码规范
########## -> 内容 <- ##########
a - JavaScript 语法 【 初级 】
1 - 赋值
var x = 1;
2 - 注释
// var x = 1;
/*
var x = 1;
var y = 2;
*/
3 - 数据类型
3.1 - Number
1
0.1
-99
NaN // NaN 表示 Not a Number,当无法计算结果时用 NaN 表示,如 0/0
Infinity // Infinity 表示无限大,如 2/0
3.2 - 字符串
'abc'
"abc" // 推荐 单引号 因为输入比较快
'a' + 'b' // 'ab'
var str = 'C'
var strNew = `12${str}34` // 模版字符串 'aCb' 【 ## ES6 新增 ## 】 *********
console.info(strNew)
长度
.length
字符串常用方法
.toUpperCase()
.toLowerCase()
.indexOf('xxx') // 返回索引
.substring(startIndex, endIndex) // 指定索引区间的子串 【 不含 endIndex | 原字符串不变 】
3.3 - 布尔
true false
3.4 - null 和 undefined
null 表示一个空值
undefined 表示未定义
区分两者的意义不大。
大多数情况下,我们都应该用 null。
undefined 仅仅在判断函数参数是否传递的情况下有用。
3.5 - 数组
var ls = [1, 'a', false, null]
new Array(1, 'a', true) // [1, 'a', true] 出于代码的可读性考虑,强烈建议直接使用[]
索引初始值为 0,即 ls[0] = 1
长度
.length
数组常用方法
.indexOf('x')
.slice(startIndex, endIndex) // 截取 Array 的部分元素,返回新 Array 【 不含 endIndex | 原数组不变 】
.push() // 向 Array 的末尾添加若干元素 返回 插入后的长度 【 原数组改变 】
.pop() // 把 Array 的最后一个元素删除掉 返回 删除的元素 【 原数组改变 】
.unshift() // 向 Array 的头部添加若干元素 返回 插入后的长度 【 原数组改变 】
.shift() // 把 Array 的第一个元素删除掉 返回 删除的元素 【 原数组改变 】
.sort() // 默认排序 [1, 3, 2].sort() // [1, 2, 3] 【 可自定义规则 ## 见 函数 -> 高阶函数 ## | 原数组改变 】
.reverse() // 反转 [1, 3, 2].reverse() // [2, 3, 1] 【 原数组改变 】
.splice(index, howmany, item1, ...) 【 *** 非常好用 ***】
var arr = ['a', 'b', 'c']
arr.splice(0, 1) // 返回 删除的元素 ['a'] arr->['b', 'c'] 【 原数组改变 】
arr.splice(0, 0, 'd') // 返回 删除的元素 [] arr->["d", "a", "b", "c"]
.concat(arr2) // 将 Array 与 另一个 Array 连接 返回 拼接后数组 【 原数组不变 】
.join(string) // 把 Array 的每个元素都用指定的字符串连接起来,返回 连接后的字符串 【 原数组不变 】
var arr = ['A', 'B', 'C', 1, 2, 3]
arr.join('-'); // 'A-B-C-1-2-3'
3.6 - 对象
var obj = {
name: 'Jack',
city: 'Shenyang'
xk-key: 'abc'
}
obj.name // 'Jack'
obj.name = 'Tom'
obj.xk-key // error
obj['xk-key'] // 'Tom'
删除属性
delete obj.name // obj.name -> undefined
属性是否存在
'city' in obj // true
注意:
如果 in 判断一个属性存在,这个属性不一定是 obj 的。
它可能是 obj 继承得到的:
'toString' in obj // true
因为 toString 定义在 object 对象中,而所有对象最终都会在原型链上指向 object,所以 obj 也拥有 toString 属性
## 原型链原理略 ##
判断一个属性是否是 obj 自身拥有的,而非继承得到的,可以用 hasOwnProperty() 方法:
var objNew = {
name: 'abc'
}
objNew.hasOwnProperty('name') // true
objNew.hasOwnProperty('toString') // false
3.7 - 变量
变量名是大小写英文、数字、$和_的组合,且不能用数字开头。
变量名也不能是 JavaScript 的关键字,如 if、while 等。
申明一个变量用 var 语句。
var $b = 1
弱类型
$b = 'abc'
3.8 - 比较运算符
>
<
>=
<=
== 比较,它会自动转换数据类型再比较,很多时候,会得到非常诡异的结果。
=== 它不会自动转换数据类型,如果数据类型不一致,返回false,如果一致,再比较。
NaN 这个特殊的 Number 与所有其他值都不相等,包括它自己。
NaN === NaN // false
判断 NaN 的方法
isNaN(NaN) // true
最后要注意浮点数的相等比较
1 / 3 === (1 - 2 / 3) // false
这不是 JavaScript 的设计缺陷。浮点数在运算过程中会产生误差,因为计算机无法精确表示无限循环小数。
要比较两个浮点数是否相等,只能计算它们之差的绝对值,看是否小于某个阈值:
Math.abs(1 / 3 - (1 - 2 / 3)) < 0.0000001 // true 【 JavaScript Math(算数)对象 】
4 - 条件判断
if (case1) {
// do something
} else {
// do something
}
if (case1)
console.info('do something') // 如果语句块只包含一条语句,可省略 {} 【不建议这样写,一旦超过一行就会容易出错】
else
console.info('do something')
if (case1) {
// do something
} else if (case2) {
// do something
} else {
// do something
}
5 - 循环
a -
var ls = [1, 2, 3]
for (var i = 0; i < ls.length; i++) {
console.info(ls[i])
}
for 循环的 3 个条件都是可以省略,如果没有退出循环的判断条件,就必须使用 break 语句退出循环,否则就是死循环
var x = 0
for (;;) { // 将无限循环下去
if (x > 100) {
break // 通过 if 判断来退出循环
}
x++
}
b -
for...in 把一个对象的所有属性依次循环出来
var o = {
name: 'Jack',
age: 20,
city: 'Beijing'
}
for (var key in o) {
console.log(key); // 'name', 'age', 'city'
}
由于 Array 也是对象,而它的每个元素的索引被视为对象的属性,因此,for...in 循环可以直接循环出 Array 的索引
var a = ['A', 'B', 'C']
for (var i in a) {
console.log(i) // '0', '1', '2'
console.log(a[i]) // 'A', 'B', 'C'
}
注意,for...in 对 Array 的循环得到的是 String 而不是 Number
c -
var n = 99
while (n > 0) {
// do something
n = n - 1 // n--
}
d -
do {...} while(),它和 while 循环的唯一区别在于,不是在每次循环开始的时候判断条件,而是在每次循环完成的时候判断条件
var n = 0
do {
// do something
n = n + 1 // n++
} while (n < 100)
注意,用 do {...} while() 循环要小心,循环体会至少执行1次,而 for 和 while 循环则可能一次都不执行
6 - 函数
a - 定义
function funA (params) {
return
}
var funA = function (params) {
// return
}
注意,函数体内部的语句在执行时,一旦执行到 return 时,函数就执行完毕,并将结果返回。
因此,函数内部通过条件判断和循环可以实现非常复杂的逻辑。
如果没有 return 语句,函数执行完毕后也会返回结果,结果为 undefined。
b - 调用
funA()
funA(123, 'xyz') // JavaScript 允许传入任意个参数而不影响调用,参数个数不影响调用
c - 变量作用域与解构赋值
## 略 ##
d - 高阶函数
1 - map
var ls = [11, 22, 33]
ls.map(item => {
console.info(item) // 11 22 33
})
var ls = [11, 22, 33]
ls.map((item, index, ls) => {
console.info(index) // 0 1 2
console.info(item) // 11 22 33
console.info(ls) // 11 22 33
})
2 - reduce
## 略 ##
3 - filter 【 原数组不变 】
var arr = [1, 2, 4, 5, 6, 9, 10, 15]
var r = arr.filter(function (x) {
return x % 2 !== 0 // 据返回值是 true 还是 false 决定保留还是丢弃该元素
})
console.info(r) // [1, 5, 9, 15]
4 - sort
[10, 20, 1, 2].sort(); // [1, 10, 2, 20]
无法理解的结果
因为 Array 的 sort() 方法默认把所有元素先转换为 String 再排序,
结果 '10' 排在了 '2' 的前面,因为字符 '1' 比字符 '2' 的 ASCII 码小
var a = '1'
var b = '2'
a.charCodeAt() // 49 String.fromCharCode(49)
b.charCodeAt() // 50
通常规定,对于两个元素 x 和 y,
如果 x < y,则返回 -1,
如果 x === y,则返回 0,
如果 x > y,则返回 1
var arr = [10, 20, 1, 2]
console.info(arr.sort())
arr.sort(function (x, y) {
if (x < y) {
return -1
}
if (x > y) {
return 1
}
return 0
})
console.log(arr) // [1, 2, 10, 20]
arr.sort(function (x, y) {
if (x < y) {
return 1
}
if (x > y) {
return -1
}
return 0
})
console.log(arr) // [20, 10, 2, 1]
5 - Array
除了 map()、reduce、filter()、sort() 这些方法可以传入一个函数外,Array对象还提供了很多非常实用的高阶函数。
5.1 - every 判断数组的所有元素是否满足测试条件
var arr = ['Apple', 'pear', 'orange']
console.log(arr.every(function (s) {
return s.length > 0
})) // true 因为每个元素都满足s.length>0
console.log(arr.every(function (s) {
return s.toLowerCase() === s;
})) // false 因为不是每个元素都全部是小写
5.2 - find 用于查找符合条件的第一个元素,如果找到了,返回这个元素,否则,返回 undefined
var arr = ['Apple', 'pear', 'orange']
console.log(arr.find(function (s) {
return s.toLowerCase() === s
})) // 'pear' 因为pear全部是小写
console.log(arr.find(function (s) {
return s.toUpperCase() === s
})) // undefined 因为没有全部是大写的元素
5.3 - findIndex 和 find 类似,也是查找符合条件的第一个元素,返回这个元素的索引,如果没有找到,返回-1
5.4 - forEach 和 map 类似,它也把每个元素依次作用于传入的函数,但不会返回新的数组
var arr = [0, 2, 4, 6, 8]
var str = arr.map(function(item, index, arr) { // 原数组arr
console.log("原数组arr:", arr)
return item/2
}, this)
console.log(str) // [0, 1, 2, 3, 4]
var arr = [0, 2, 4, 6, 8]
var sum = 0
var str = arr.forEach(function(item, index, arr) { // 原数组arr
sum += item
console.log("sum的值为:", sum) //0 2 6 12 20
},this)
console.log(str); // undefined
e - 闭包
## 略 ##
f - 箭头函数 【 ## ES6 新增 ## 】
x => x * x
等价于
function(x) {
return x * x
}
(x, y) => {
// do something
// return
}
箭头函数相当于匿名函数,并且简化了函数定义。
箭头函数有两种格式,
一种像上面的,只包含一个表达式,{...} 和 return 都省略掉了。
还有一种可以包含多条语句,这时候就不能省略 {...} 和 return
x => {
if (x > 0) {
return x * x
} else {
return - x * x
}
}
如果要返回一个对象,就要注意,如果是单表达式,这么写的话会报错:
x => { foo: x } // SyntaxError:
因为和函数体的 {...} 有语法冲突,所以要改为:
x => ({ foo: x })
this
箭头函数和匿名函数有个明显的区别:
箭头函数内部的 this 是词法作用域,由上下文确定。
简单的说就是,箭头函数与包围它的代码共享同一个this。
前面的例子,由于 JavaScript 函数对 this 绑定的错误处理,下面的例子无法得到预期结果:
var obj = {
birth: 1990,
getAge: function () {
var b = this.birth // 1990
var fn = function () {
return new Date().getFullYear() - this.birth // this 指向 window 或 undefined
}
return fn()
}
}
obj.getAge() // NaN
现在,箭头函数完全修复了this的指向,this总是指向词法作用域,也就是外层调用者obj:
var obj = {
birth: 1990,
getAge: function () {
var b = this.birth // 1990
var fn = () => new Date().getFullYear() - this.birth // this 指向 obj 对象
return fn()
}
}
obj.getAge() // 30
g - generator
## 略 ##
7 - 标准对象
a - Date
var now = new Date()
now; // Wed Jun 24 2015 19:49:22 GMT+0800 (CST)
now.getFullYear(); // 2015, 年份
now.getMonth(); // 5, 月份,注意月份范围是0~11,5表示六月 【 *** 】
now.getDate(); // 24, 表示24号
now.getDay(); // 3, 表示星期三
now.getHours(); // 19, 24小时制
now.getMinutes(); // 49, 分钟
now.getSeconds(); // 22, 秒
now.getMilliseconds(); // 875, 毫秒数
now.getTime(); // 1435146562875, 以number形式表示的时间戳
说明:
VUE 中推荐使用 Moment.js
b - RegExp
## 略 ##
说明:
搜索关键字 【 js 正则 30 分钟入门 】
c - JSON
历史起源:
## 略 ##
JavaScript 的 JSON 实际上是 JavaScript 的一个子集。
在JSON中,一共就这么几种数据类型:
number:和 JavaScript 的 number 完全一致;
boolean:就是 JavaScript 的 true 或 false;
string:就是 JavaScript 的 string;
null:就是 JavaScript 的 null;
array:就是 JavaScript 的 Array 表示方式——[];
object:就是 JavaScript 的 {...} 表示方式。
1 - 序列化
var obj = {
name: '小明',
age: 15,
gender: true,
skills: ['JavaScript', 'Java', 'Python']
}
JSON.stringify(obj) // "{"name":"小明","age":15,"gender":true,"skills":["JavaScript","Java","Python"]}"
2 - 反序列化
JSON.parse('[1,2,3,true]'); // [1, 2, 3, true]
JSON.parse('{"name":"小明","age":14}'); // Object {name: '小明', age: 14}
JSON.parse('true'); // true
JSON.parse('123.45'); // 123.45
3 - 其他高级用法
## 略 ##
8 - 面向对象编程
## 略 ##
9 - 浏览器对象
## 略 ##
10 - 错误处理
## 略 ##
11 - 缓存
cookie sessionStorage localStorage
特性 Cookie localStorage sessionStorage
数据的生命期 一般由服务器生成, 除非被清除,否则永久保存 仅在当前会话下有效,关闭页面或浏览器后被清除
可设置失效时间
如果在浏览器端成Cookie
默认是关闭浏览器后失效
存放数据大小 4 K 左右 一般为 5 MB
与服务器端通信 每次都会携带在HTTP头中, 仅在客户端(即浏览器)中保存,不参与和服务器的通信
如果cookie保存过多数据,
会带来性能问题
易用性 需要自己封装, 源生接口可以接受,亦可再次封装来对 Object 和 Array 有更好的支持
源生Cookie接口不友好
setItem 存储 value
window.sessionStorage.setItem("key", "key-value")
localStorage.setItem("site", "site-value")
getItem 获取 value
var value = sessionStorage.getItem("key")
var site = localStorage.getItem("site")
removeItem 删除 key
sessionStorage.removeItem("key")
localStorage.removeItem("site")
clear 清除所有的 key/value
sessionStorage.clear()
localStorage.clear()
12 - setTimeout setInterval
二者均是 window 对象 的 method。
所有 JavaScript 全局对象、函数以及变量均自动成为 window 对象的成员。
全局变量是 window 对象的属性。
全局函数是 window 对象的方法。
setTimeout(fn,1000) 超时调用,超过时间t,就执行fn。
setInterval(fn,t) 间歇调用,调用周期t,执行fn。
二者调用后,均返回一个数值 ID,此 ID 是计划执行代码的唯一标识符,可以通过它来取消尚未执行的调用。
clearTimeout(id)
clearInterval(id)
13 - js 执行机制
a - JavaScript 是一门单线程语言。
所谓单线程,是指执行代码的时候是从上往下执行的。
b - Event Loop(事件循环)是 JavaScript 的执行机制。
【 推荐 帖子 https://www.jianshu.com/p/1368d375aa66 】
b - ES6 语法 【 初级 】
说明:
a - 仅介绍高频使用的语法
b - Babel 是一个广泛使用的 ES6 转码器,可以将 ES6 代码转换为 ES5 代码
1 - let const 块级作用域
let 和 var声明的区别:
var name = 'Jack'
while(true) {
var name = 'Tom'
console.info(name) // Tom
break
}
console.info(name) // Tom
let name = 'Jack'
while(true) {
let name = 'Tom'
console.info(name) // Tom
break
}
console.info(name) // Jack
let 表示声明变量
const 表示声明常量
const 声明的变量都会被认为是常量,它的值被设置完成后就不能再修改了
const a = 1
a = 0 // 报错
如果 const 的是一个对象,对象所包含的值是可以被修改的。抽象一点儿说,就是对象所指向的地址没有变就行:
const student = { name: 'cc' }
student.name = 'yy' // 不报错
student = { name: 'yy' } // 报错
注意:
1 - let 和 const 声明只在最靠近的一个块中(花括号内)有效
2 - 常量 const 声明时,请使用大写变量,如:const PI = 3.14
3 - const 在声明时必须被赋值
2 - 模版字符串 template string
## 数据类型 -> 字符串 章节已做说明 ##
3 - 箭头函数 arrow functions
## 函数 -> 箭头函数 章节已做说明 ##
4 - 解构 destructuring
// 对象
const people = {
name: 'Jack',
age: 20
}
const { name, age } = people
console.log(name) // Jack
console.log(age) // 20
// 数组
const color = ['red', 'blue']
const [first, second] = color
console.log(first) // 'red'
console.log(second) // 'blue'
5 - 展开运算符 spread operator
// 数组
const color = ['red', 'yellow']
const colorful = [...color, 'green', 'pink']
console.log(colorful) // [red, yellow, green, pink]
// 对象
const alp = { fist: 'a', second: 'b'}
const alphabets = { ...alp, third: 'c' } // 英[ˈælfəbɪts]
console.log(alphabets) // { "fist": "a", "second": "b", "third": "c" }
6 - 函数参数默认值 default arguments
function funA (type = 1) {
console.info(type)
}
funA() // 1
7 - 模块化 module export import
导出
导出变量
// test.js
export let name = 'Rainbow'
export default App
ES6 将一个文件视为一个模块,上面的模块通过 export 向外输出了一个变量。
一个模块也可以同时往外面输出多个变量。
// test.js
let name = 'Rainbow'
let age = '24'
export { name, age }
导出函数
// myModule.js
export function funA(someArg) {
return someArg;
}
导入
定义好模块的输出以后就可以在另外一个模块通过 import 引用。
import { funA } from 'myModule' // main.js
import { name, age } from 'test' // test.js
funA()
// 全部导入
import people from './example.js'
// 有一种特殊情况,即允许你将整个模块当作单一对象进行导入
// 该模块的所有导出都会作为对象的属性存在
import * as example from "./example.js"
console.log(example.attribute)
console.log(example.method())
说明:
1 - 当用 export default people 导出时,就用 import people from 'xxx' 导入(不带大括号)
2 - 一个文件里,有且只能有一个 export default。但可以有多个 export。
3 - 当用 export name 时,就用 import { name } from 'xxx' 导入(记得带上大括号)
4 - 当一个文件里,既有一个 export default people, 又有多个 export name 或者 export age时,
导入就用 import people, { name, age } from 'xxx'
5 - 当一个文件出现 n 个 export 导出很多模块,导入时除了一个一个导入,也可以用 import * as module from 'xxx'
8 - Promise resolve reject
Promise 是异步编程的一种解决方案,比传统的解决方案 callback 过多的回调或者嵌套,可读性差,耦合度高,扩展性低)更加的优雅。
// 不使用ES6
setTimeout(function() {
console.log('Hello') // 1 秒后输出 "Hello"
setTimeout(function() {
console.log('Hi'); // 2 秒后输出 "Hi"
}, 1000)
}, 1000)
var funDealy = function() {
return new Promise((resolve, rejecet) => {
setTimeout(() => {
console.info('3000')
resolve(true)
}, 3000)
})
}
funDealy().then(res => {
console.info(res)
console.info('3001')
})
// 使用ES6
var waitSecond = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
/*
let i = 0
for (;;) {
i++
if (i > 10000) {
console.info('end for')
break;
}
}
*/
resolve('resolve means 成功')
// reject('reject means 失败')
}, 3000)
})
}
waitSecond()
.then((res) => {
// resolve
console.info(res)
console.log("Hello") // 1 秒后输出 "Hello"
return waitSecond()
})
.then((res) => {
// resolve
console.info(res)
console.log("Hi") // 2 秒后输出 "Hi"
})
.catch((err) => {
// reject
console.info(err)
})
.finally((res) => {
console.info('finally')
})
Promise 高级用法 Promise.all 等
## 略 ##
9 - async await 【 asynchronous 英 [eɪˈsɪŋkrənəs] adj. 不同时存在(或发生)的; 非共时的 】
async 函数返回一个 Promise 对象,可以使用 then 方法添加回调函数。
当函数执行的时候,一旦遇到 await 就会先返回,等到异步操作完成,再接着执行函数体内后面的语句。
var asyncFunc = () => {
return new Promise((resolve, reject) => {
let a = 0
setTimeout(() => {
while(a < 100) {
a += Math.round(Math.random() * 10) // round 四舍五入 ceil 向上取整 floor 向下取整
}
resolve(a)
}, 3000)
})
}
async function awaitFunc() {
const result = await asyncFunc()
console.info(result)
}
10 - 类 class extends super
## 略 ##
11 - 生成器 Generators
## 略 ##
c - MVVM 框架讲解
d - VUE 原理讲解
e - VUE 语法 【 初级 】
f - VUE 脚手架 及 webpack 配置 【 基础 】
g - chrome 调试方法 【 初级 】
1 - 调试功能说明
现场演示
2 - 打印 log
console.log('1')
console.info('2')
console.warn('3')
console.error('4')
console.info('%c 123', 'font-size: 100px; color: red;')
########## -> 特别说明 <- ##########
以上内容主要来源:
1 - 廖雪峰 老师 博客(廖雪峰的官方网站 等)
2 - 阮一峰 老师 博客(ECMAScript 6 入门 等)
3 - W3school