一、什么是ECMA?
ECMA是标准,js是实现。
ECMAscript 简写 ECMA 或者 ES
目前版本:
低级浏览器:主要支持ES3.1
高级浏览器:正在从ES5过渡到ES6
二、常用到的编译工具
Tranceur 由google出的编译器,把ES6语法编译为ES5
Bootstrap 引导程序,跟css里面认识的bootstrap不一样
用法 :
用法 一:
在网页上使用:
<script src=”traceur.js”></script>
<script src=” bootstrap.js”></script>
<script type=”module”></script>
用法二:
直接在线编译——主要用于测试
https://babeljs.io/repl
用法三:
直接在node中使用
三、 定义变量,let
代码块:{}包起来的代码,形成了一个作用域,块级作用域,比如:if for while
特点:只能在代码块里面使用,var有函数作用域
- let具备块级作用域(一是内层变量可能会覆盖外层变量。二是用来计数的循环变量泄露为全局变量。)
- 不允许冲重复声明
- let定义的变量不会被变量提升
- 暂时性死区。 在代码块内,使用let命令声明变量之前,该变量都是不可用的。这在语法上,称为“暂时性死区”
总结:其实let才接近其他语言的变量
用处:
封闭空间:
(function(){
//code
})()
现在:
{
}
总结:块级作用域,其实就是匿名函数立即调用
案例:
var arr = [];
for(let i = 0 ; i < 10 ; i++){
arr[i] = function(){
console.log(i);
}
}
arr[6](); //6
var arr = [];
for(var i = 0 ; i < 10 ; i++){
arr[i] = function(){
console.log(i);
}
}
arr[6](); //10
块级作用域与函数声明:
ES5 规定,函数只能在顶层作用域和函数作用域之中声明,不能在块级作用域声明。
ES6 引入了块级作用域,明确允许在块级作用域之中声明函数。ES6 规定,块级作用域之中,函数声明语句的行为类似于let,在块级作用域之外不可引用。
四、 const——用来定义常量
const声明一个只读的常量。一旦声明,常量的值就不能改变。
const一旦声明变量,就必须立即初始化,不能留到以后赋值。 因为以后再没法赋值了,所有声明的时候一定有值
只在声明所在的块级作用域内有效
const命令声明的常量也是不提升,同样存在暂时性死区,只能在声明的位置后面使用。
用途:为了防止意外修改变量
比如:引入库名,组件库
五、 字符串链接:
之前:‘abc’+变量名+‘ef’
`字符串连接${变量名}`
let obj = {f:'first',l:'last'};
var box = document.getElementById('box');
console.log(box);
var str = `
<ul>
<li>${obj.f}</li>
<li>${obj.l}</li>
</ul>
`;
console.log(str);
box.innerHTML=str;
字符串的遍历:
for(let str of 'abc'){
console.log(str);
}
CharAt()方法:
'abc'.charAt(2)
三种方法:
includes():返回布尔值,表示是否找到了参数字符串。
startsWith():返回布尔值,表示参数字符串是否在原字符串的头部。
endsWith():返回布尔值,表示参数字符串是否在原字符串的尾部。
repeat方法返回一个新字符串,表示将原字符串重复n次。
ES7:
padStart()用于头部补全,padEnd()用于尾部补全。
onsole.log('aa'.padStart(4,'12345'));
console.log('aa'.padEnd(4,'12345'));
六、 解构赋值
a) 什么是解构赋值
ES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构
本质上,这种写法属于“模式匹配”,只要等号两边的模式相同,左边的变量就会被赋予对应的值。
var [a,b,c] = [12,4,5];
var {a,b,c} = {a:23,b:4,c:33} 跟顺序无关
模式匹配: 左侧和右侧模式必须一样
var [a,[b,c],c] = [2,[2,3],4];
var [a,b,{a,b}] = [2,3,{‘aa’,’bb’}]
b) 数组的解构赋值
案例
let [a,b,c] = [1,2,3];
console.log(a+b+c); //6
let [foo,[[bar]],baz] = [1,[[2]],3];
console.log(a+b+c); //6
let [ , ,third] = ["foo","bar","baz"];
console.log(third); //baz
let [head, ...tail] = [1,2,3,4];
console.log(tail); //[ 2, 3, 4 ]
let [x,y,...z] = ['a'];
console.log(x); //a
console.log(y); //undefined
console.log(z); //[]
以下情况是不完全解构,即等号左边的模式,只匹配一部分的等号右边的数组
let [aaa,bbb] = [1];
console.log(aaa); //1
注:
如果等号的右边不是数组(或者严格地说,不是可遍历的结构),那么将会报错。
事实上,只要某种数据结构具有 Iterator 接口,都可以采用数组形式的解构赋值。
c) 默认值
解构赋值允许指定默认值。
案例 :
let [foo = true] = [];
foo // true
let [x, y = 'b'] = ['a']; // x='a', y='b'
let [x, y = 'b'] = ['a', undefined]; // x='a', y='b'
注意,ES6 内部使用严格相等运算符(===),判断一个位置是否有值。所以,只有当一个数组成员严格等于undefined,默认值才会生效。
d) 对象的解构赋值
对象的解构与数组有一个重要的不同。数组的元素是按次序排列的,变量的取值由它的位置决定;而对象的属性没有次序,变量必须与属性同名,才能取到正确的值。
案例:
let {bar,foo} = {foo:"aaa",bar:"bbb"};
console.log(bar+foo); //bbbaaa
let {bar:b,foo:f} = {foo:"aaa",bar:"bbb"};
console.log(b+f); //bbbaaa
let obj = {
p: ['hello',{y:'world'}]
}
let {p:[x,{y}]} = obj;
console.log(x+y); //helloworld
const node = {
loc: {
start: {
line: 1,
column: 5
}
}
}
let {loc,loc:{start},loc:{start:{line}}} = node;
// line // 1
// loc // Object {start: Object}
// start // Object {line: 1, column: 5}
let obj2 = {};
let arr2 = [];
({foo2:obj2.pro,bar2:arr2[0]}={foo2:123,bar2:456});
console.log(obj2,arr2);
对象的解构赋值的内部机制,是先找到同名属性,然后再赋给对应的变量。真正被赋值的是后者,而不是前者。
默认值:对象的解构也可以指定默认值。
var {x, y = 5} = {x: 1};
x // 1
y // 5
e) 字符串的解构赋值
const [a,b,c,d,e] = "hello";
console.log(a,b,c,d,e); //hello
let {length:len} = "hello";
console.log(len); //5
f) 数值和布尔值的解构赋值
解构赋值时,如果等号右边是数值和布尔值,则会先转为对象
注:解构赋值的规则是,只要等号右边的值不是对象或数组,就先将其转为对象。由于undefined和null无法转为对象,所以对它们进行解构赋值,都会报错。
七、 复制数组
(1).var arr = [2,3,4,5];
var arr2 = Array.from(arr);
(2). var arr = [2,3,4,5];
var arr2 = [];
for(var i = 0 ; i < arr.length ; i++){
arr2[i]=arr[i]
}
(3). var arr2 = [...arr];
案例:
function show(...args){
console.log(...args);
}
show(1,2,3,4);
八、 循环(遍历,迭代)整个对象,表现类似for in
var arr = ['aa','bb','dd'];
for(var i in arr){
console.log(arr[i]);
} //for in 循环数组,i为下标
for(var i of arr){
console.log(i);
} //for of 循环数组,i为值
var json = {'a':'apple','b':'banan','o':'orange'};
for(var i in json){
console.log(json[i]);
} // for in 循环数组,数组为键,但不能用for of 循环json
九、 map
a) map和object比较
JavaScript 的对象(Object),本质上是键值对的集合(Hash 结构),但是传统上只能用字符串当作键。这给它的使用带来了很大的限制。
Map 数据结构。它类似于对象,也是键值对的集合,但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键。也就是说,Object 结构提供了“字符串—值”的对应,Map 结构提供了“值—值”的对应
var map = new Map();
map.set('a','apple'); //设置值
map.set('b','banana');
map.set('o','orange');
console.log(map);
console.log(map.get('a')); //获取值
console.log(map.get('b'));
map.delete('a'); //删除
console.log(map);
//遍历map
for(var name of map){
console.log(name); //键值
}
for(var [key,value] of map){
console.log(key,value); //键和值
}
for(var name of map.entries()){ //默认
}
for(var key of map.keys()){
console.log(key); //只循环键
}
for(var value of map.values()){
console.log(value); //只循环值
}
for of 也可循环数组,但不能单独循环值
十、 箭头函数
=>
window.onload = ()=> {
var box = document.getElementById('box');
box.onclick = ()=> {
//this 是window,不是当前对象
box.style.backgroundColor = 'red';
}
}
函数的默认值
function move(obj=’aa’,json={},options){}
注意:this的问题,指向了window ;arguments,不能使用this
十一、对象
对象语法简洁化
var name = 'a';
var age = 122;
var person = {
name,
age,
showName(){
return this.name;
},
showAge(){
return this.age;
}
}
面向对象:
Es5:
function Person(name,age){ //类,构造函数
this.name = name;
this.age = age;
}
Person.prototype.showName = function(){
return this.name;
}
Person.prototype.showAge = function(){
return this.age;
}
var p1 = new Person('aaa',23);
console.log(p1.showName());
es6:
类: class
构造函数: constructor 生成完实例以后,自己就执行的
class Person{
constructor(name='default',age=0){ 函数的默认值
this.name = name ;
this.age = age;
}
showName(){
return this.name;
}
showAge(){
return this.age;
}
}
var p = new Person('aaa',12);
console.log(p.showName());
继承:
Es5:
子类.prototype = new 父类();
Es6:
class Worker extends Person{}
var w1 = new Worker('mmm',232);
console.log(w1.showAge());
class Worker extends Person{
constructor(name,age,job='扫地的'){
super(); //调用父级的构造
this.job = job;
}
showJob(){
return this.job;
}
}
var w1 = new Worker('mmm',232);
console.log(w1.showAge());
console.log(w1.showJob());
十二、模块化
必须引入traceur和bootstrap,type必须写成module
ES6自带模块化
如何定义(导出)模块
const a = 12;
export default a;
const b = 12;
export default {a,b}
如何使用(引用)
Import modA from ‘./a.js’
十三、Promise——承诺
就是一个对象,用来传递异步操作的数据(消息)
异步:多个操作可以同时进行
三种状态:
pendingz(等待、处理中)——》Resolve(完成)
——》Rejected(拒绝、失败)
var p1 = new Promise(function(resolve,reject){
//resolve 成功了
//reject 失败了
});
var p1 = new Promise(function(resolve,reject){
if(异步处理成功了){
resolve(成功的数据)
}else{
reject(失败的原因)
}
});
p1.then(成功(resolve),失败(reject))
用处:用于解决异步数据获取时数据向外传递,例如ajax获取的数据向外传递
catch:用来捕获错误
all: 全部,用于将多个promise对象,组合,包装成一个全新的promise实例。
Promise.aa([p1,p2,p3]);
所有的promise对象,都正确,才走成功
否则,只要有一个错误,是失败了
race —返回也是一个promise对象
最先能执行的promise结果,那个最快,用哪个。
十五、ECMAscript和javascript区别:
ECMAScript 和 JavaScript 的关系是,前者是后者的规格,后者是前者的一种实现(另外的 ECMAScript 方言还有 Jscript 和 ActionScript)。日常场合,这两个词是可以互换的。
十六、Symbol
ES6 引入了一种新的原始数据类型Symbol,表示独一无二的值。它是 JavaScript 语言的第七种数据类型,前六种是:undefined、null、布尔值(Boolean)、字符串(String)、数值(Number)、对象(Object)。
案例:
let s1 = Symbol();
let s2 = Symbol();
console.log(s1 === s2); //false
let s11 = Symbol('aaa');
let s22 = Symbol('bbb');
console.log(s11 === s22); //false
十七、数值的扩展(Number)
Number.isFinite()用来检查一个数值是否为有限的(finite),即不是Infinity。
Number.isNaN()用来检查一个值是否为NaN。
ES6 将全局方法parseInt()和parseFloat(),移植到Number对象上面,行为完全保持不变。
Number.isInteger()用来判断一个数值是否为整数。
Math.trunc方法用于去除一个数的小数部分,返回整数部分。
Math.sign方法用来判断一个数到底是正数、负数、还是零。对于非数值,会先将其转换为数值。
十七、Set数据结构
ES6 提供了新的数据结构 Set。它类似于数组,但是成员的值都是唯一的,没有重复的值。
Set 本身是一个构造函数,用来生成 Set 数据结构。
const s = new Set();
[2,3,4,4,6,7].forEach(x => s.add(x));
for(let i of s){
console.log(i);
}
const set = new Set([2,3,4,4,6,7]);
console.log(...set);
console.log(set.size);
数组去重:
展示了一种去除数组重复成员的方法。
[...new Set(array)]
const items = new Set([1,2,3,4,5,5]);
const array = Array.from(items);
console.log(items);
console.log(array);
Set的属性:
set.size,返回Set实例的成员总数。
Set的方法:Set 实例的方法分为两大类:操作方法(用于操作数据)和遍历方法(用于遍历成员)。
• add(value):添加某个值,返回 Set 结构本身。
• delete(value):删除某个值,返回一个布尔值,表示删除是否成功。
• has(value):返回一个布尔值,表示该值是否为Set的成员。
• clear():清除所有成员,没有返回值。
Set的遍历操作:
• keys():返回键名的遍历器
• values():返回键值的遍历器
• entries():返回键值对的遍历器
• forEach():使用回调函数遍历每个成员
let set = new Set(['red','green','blue']);
for(let item of set.keys()){
console.log(item);
}
for(let item of set.values()){
console.log(item);
}
for(let item of set.entries()){
console.log(item);
}
set.forEach(x => console.log(x));
let arr = [...set];
console.log(arr);
十八、Map
JavaScript 的对象(Object),本质上是键值对的集合(Hash 结构),但是传统上只能用字符串当作键。这给它的使用带来了很大的限制。
Map实例属性
(1) size 属性 size属性返回 Map 结构的成员总数
(2) set(key, value) set方法设置键名key对应的键值为value,然后返回整个 Map 结构。如果key已经有值,则键值会被更新,否则就新生成该键。
(3) get(key) get方法读取key对应的键值,如果找不到key,返回undefined。
(4)has(key) has方法返回一个布尔值,表示某个键是否在当前 Map 对象之中。
(5)delete(key) delete方法删除某个键,返回true。如果删除失败,返回false。
(6)clear()clear方法清除所有成员,没有返回值。
遍历方法 §
Map 结构原生提供三个遍历器生成函数和一个遍历方法。
• keys():返回键名的遍历器。
• values():返回键值的遍历器。
• entries():返回所有成员的遍历器。
• forEach():遍历 Map 的所有成员
const map = new Map([
['f','no'],
['t','yes']
]);
for(let key of map.keys()){
console.log(key);
}
for(let value of map.values()){
console.log(value);
}
for(let item of map.entries()){
console.log(item);
}
map.forEach(item => console.log(item));