中软Day16
ES6
ES6概述
ES6,全称ECMA Script6.0,是 新一代的JS语言标准,发布于15年左右。
目标让js语言成为能支持去编写大型复杂的应用语言, 成为企业级开发语言。
-
ECMAscript和javascript区别:
ECMAScript 和 JavaScript 的关系是,前者是后者的规格,后者是前者的一种实现(另外的 ECMAScript 方言还有 Jscript 和 ActionScript)。日常场合,这两个词是可以互换的。
变量
-
变量有什么新特性?
可以使用let去定义变量,可以使用const去定义常量,解构赋值。 -
let命令作用:用于声明变量,类似于var,但是,它只在let所在的代码块内部有效。
<script type="text/traceur"> { var a=100; let b=200; } console.log(a); //100 console.log(b); //Error,b is not defined </script>
-
let与var的区别
-
var
var a = []; for (var i = 0; i < 10; i++) { a[i] = function () { console.log(i); }; } a[6](); // 10 /*变量i是var声明的,在全局范围内都有效,所以全局只有一个变量i。每一次循环,变量i的值都会发生改变,而循环内被赋给数组a的function在运行时,会通过闭包读到这同一个变量i,导致最后输出的是最后一轮的i的值,也就是10。
-
let
var a = []; for (let i = 0; i < 10; i++) { a[i] = function () { console.log(i); }; } a[6](); // 6 //变量i是let声明的,当前的i只在本轮循环有效,所以每一次循环的i其实都是一个新的变量,所以最后输出的是6。
-
-
性质:
-
let具备块级作用域(一是内层变量可能会覆盖外层变量。二是用来计数的循环变量泄露为全局变量。)
-
let声明的变量只能在代码块内部调用
-
没有变量提升
-
ES5
<script type="text/traceur"> //ES5 console.log("ES5"); for(var i=0;i<10;i++){ var c=i; a[i]=function(){ console.log(c); }; }; a[5](); //9 </script>
-
ES6
//在let声明变量的时候,就不会如此结果 <script type="text/traceur"> //ES6 console.log("ES6"); for(let j=0;j<10;i++){ let c=j; a[i]=function(){ console.log(c); }; }; a[5](); //5 </script>
解析:由于在执行函数时,将j=5作为变量赋值给传入函数中,所以执行完毕即退出。
-
-
暂时性死区
在代码块内,使用let命令声明变量之前,该变量都是不可用的。这在语法上,称为“暂时性死区” 。//只要块级作用域中存在let命令,所声明的该变量是有效的“绑定的”,不再受外部影响。 //a在let a声明前就console了,即表示“未定义undefined”,在let之前的区域为“暂时性死区”。 <script type="text/traceur"> //var a=100; { console.log(a); //undefined let a=100; console.log(a); //100 } </script>
<!--在该案例中,多了“var a”,但是let所声明的变量,并不在乎外界的影响,所以在let作用域内部,var声明的变量是无效的,即“console.log(a)”还是defined(3)let不允许重复声明情况1:模块内部重复声明(不允许用let命令重复声明)> <script type="text/traceur"> var a=100; { console.log(a); //undefined let a=100; console.log(a); //100 } </script>
-
变量作用域不同
<script type="text/trancer"> { var a=1; var a=2; console.log(a); //2 } { let a=2; console.log(a); //2 } </script>
-
-
不允许重复声明
let不允许在相同作用域内部重复声明同一个变量,所以也是不允许在函数中重新声明参数。<script type="text/trancer"> { var a=1; var a=2; } console.log(a); //2 { var b=1; let b=2; } console.log(b); { let c=1; let c=2; } console.log(c); </script> //解析:由于var重复声明的变量是可以运行的,即后边的会覆盖前边的变量。但是,只要声明的变量存在let,则若重复声明一个变量,都会报错。无论有一个let,let在前还是在后;还是有两个重复let声明的变量,都是有错误的。
模块之间不影响,可重复声明
<script type="text/trancer"> { var a=1; var a=2; console.log(a); //2 } { let a=2; console.log(a); //2 } </script>
-
const,var,let三者区别
-
const定义的变量不可以修改,而且必须初始化。
const b = 2;//正确 // const b;//错误,必须初始化 console.log('函数外const定义b:' + b);//有输出值 // b = 5; // console.log('函数外修改const定义b:' + b);//无法输出
-
var定义的变量可以修改,如果不初始化会输出undefined,不会报错。
var a = 1; // var a;//不会报错 console.log('函数外var定义a:' + a);//可以输出a=1 function change(){ a = 4; console.log('函数内var定义a:' + a);//可以输出a=4 } change(); console.log('函数调用后var定义a为函数内部修改值:' + a);//可以输出
-
let是块级作用域,函数内部使用let定义后,对函数外部无影响。
let c = 3; console.log('函数外let定义c:' + c);//输出c=3 function change(){ let c = 6; console.log('函数内let定义c:' + c);//输出c=6 } change(); console.log('函数调用后let定义c不受函数内部定义影响:' + c);//输出c=3
块级作用域
-
ES5 VS ES6
ES5:在ES5中,只有两种作用域:全局作用域 + 局部作用域
场景1——内部作用域会覆盖外部作用域
场景2——用于计数的循环变量泄露为全局变量(循环变量结束,变量依然存在,内存占用) -
ES6
块级作用域
//ES6:增加了“块级作用域”的概念 <script type=”text/traceur”> console.log(“ES6:”); let num=100; if(true){ let num=200; } console.log(num); //100 </script>
<script type=”text/traceur”> function fun(){console.log(“I am outside!”);} (function(){ if(false){ function fun(){ console.log(“I am inside!”); }; }; fun(); //I am outside! })();
-
ES5
<script type=”text/javascript”> console.log(“ES5”); var num=100; if(true){ var num=200; } console.log(num); //200 </script>
立即执行函数
<script type=”text/javascript”> function fun(){ Console.log(“I am outside!”); } (function(){ if(false){ function fun(){ console.log(“I am inside!”); }; }; fun(); //I am inside! })(); </script>
-
do表达式
本质上,块级作用域是一个语句,将多个操作封装在一起,没有返回值。
{ let t = f(); t = t * t + 1; }
块级作用域将两个语句封装在一起。但是,在块级作用域以外,没有办法得到t的值,因为块级作用域不返回值,除非t是全局变量。
-
do表达式可以返回值
let x = do { let t = f(); t * t + 1; }; //变量x会得到整个块级作用域的返回值。
-
-
常量
const一旦声明变量,就必须立即初始化,不能留到以后赋值。 因为以后再没法赋值了,所有声明的时候一定有值 。
只在声明所在的块级作用域内有效
const命令声明的常量也是不提升,同样存在暂时性死区,只能在声明的位置后面使用。
用途:为了防止意外修改变量
比如:引入库名,组件库
-
Const也是声明变量,但是它声明的是一个常量。一旦声明,就不能改变。
<script type=”text/traceur”> const Pi =3.1415926; console.log(Pi); Pi=3; console.log(Pi); //Pi is read-only——Error </script>
-
使用const命令
<script type=”text/traceur”> const Pi =3.1415926; console.log(Pi); Pi=3; console.log(Pi); //Pi is read-only——Error </script>
-
const块级作用域
<script type=”text/traceur”> if(true){ const Pi=3.1415926; } console.log(Pi); // Pi is not defined!——error </script>
-
const对象
<script type=”text/traceur”> const person={}; person.name=”Zhangsan”; person.age=30; console.log(person.name); console.log(person.age); console.log(person) ; //object{name: age} </script>
-
const数组
<script type=”text/traceur”> const arr=[]; console.log(arr); console.log(arr.length); console.log(“------”); arr.push(“Hello world!”); console.log(arr); console.log(arr.length); arr.length=0; console.log(arr.length); //错误用法 arr = [“Hello world”]; </script>
-
const对象冻结
<script type=”text/traceur”> const person = Object.freeze({ name = “Zhangsan”; age=12; }); //冻结对象; console.log(person.name); //Zhangsan console.log(person.age); //12 console.log(person); //Object </script>
-
彻底冻结对象
var constantize=(obj) => { object.freeze(obj); object.keys(obj).forEach(key , value) => { if( typeof obj[key] === ‘object’ ){ constantize( obj[key] ); }; }; };
用处:用于解决异步数据获取时数据向外传递,例如ajax获取的数据向外传递
- catch:用来捕获错误
- all: 全部,用于将多个promise对象,组合,包装成一个全新的promise实例。
Promise.aa([p1,p2,p3]);
所有的promise对象,都正确,才走成功
否则,只要有一个错误,是失败了 - race —返回也是一个promise对象
最先能执行的promise结果,那个最快,用哪个。
-
跨模块常量
<script type=”text/traceur”>
// module1.js
export const intVariantName =100;
export const floatVariantName =3.14;
export const charVariantName =”variantValue”;
// user.js
import * as var from ‘./module’;
console.log(variant.IntvariantName); // 100
console.log(variant.floatvariantName); //3.14
console.log(variant.charvariantName); //”variantValue”
//otherUser.js
import{intVariantName,floatVariantName } as variant from ‘./module’;
console.log(variant.IntvariantName); // 100
console.log(variant.floatvariantName); //3.14
</script>
字符串
字符串链接
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)
-
方法
JavaScript只有 indexOf 方法,可以用来确定一个字符串是否包含在另一个字符串中。ES6又提供了三种新方法。
- includes():返回布尔值,表示是否找到了参数字符串。
- startsWith():返回布尔值,表示参数字符串是否在源字符串的头部。
- endsWith():返回布尔值,表示参数字符串是否在源字符串的尾部。
解构赋值
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’}]
//通常情况下
var first = someArray[0];
var second = someArray[1];
var third = someArray[2];
//解构赋值
let [first, second, third] = someArray; //比上面简洁多了吧
//还有下面例子
let [,,third] = [1,2,3];
console.log(third); //3
let [first,...last] = [1,2,3];
console.log(last); //[2,3]
//对象解构
let {name,age} = {name: "lisi", age: "20"};
console.log(name); //lisi
console.log(age); //20
//注意
let {ept1} = {};
console.log(ept1); //undefined
let {ept2} = {undefined};
console.log(ept2); //undefined
let {ept3} = {null};
console.log(ept3); //null
-
数组的解构赋值
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 接口,都可以采用数组形式的解构赋值。-
案例
数组对应位置
let [one, ,three] =[“one”,”two”,”three”]; console.log(one); //one console.log(three); //three let [head,...tail] =[0,1,2,3,4,5]; console.log(head); //0 console.log(tail); //[1,2,3,4,5]
不完全解构
定义:等号左边的模式,只匹配一部分的等号右边的数据。(不会出现溢出等现象)
<script type=”text/traceur”> let [x,y] = [1,2,3]; console.log(x); //1 console.log(y); //2 let [a,[b],c] = [1,[2,3],4]; console.log(a); //1 console.log(b); //2 console.log(c); //4 let [a,[b,d],c] =[1,[2,3],4]; console.log(a); //1 console.log(b); //2 console.log(d); //3 </script>
-
-
默认值
解构赋值允许默认值。
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,默认值才会生效。
-
案例
指定默认值
<script type=”text/traceur”> var [temp=”string”] = []; console.log(temp); //string var [temp=”string” ]= [“tempString”]; console.log(temp); //tempString var [x=”aaa”,y] = [“bbb”]; console.log(x); //bbb console.log(y); //undefined var [m,n=”aaa”] = [“bbb”]; console.log(m); //bbb console.log(n); //aaa var [p,q=”aaa”] = [“bbb”,undefined]; console.log(p); //bbb console.log(q); //aaa(由于undefined是未定义,所以有值即输出) </script> //非遍历数组解构产生报错
-
-
对象的解构赋值
对象的解构与数组有一个重要的不同。数组的元素是按次序排列的,变量的取值由它的位置决定;而对象的属性没有次序,变量必须与属性同名,才能取到正确的值。
案例: 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);
对象的解构赋值的内部机制,是先找到同名属性,然后再赋给对应的变量。真正被赋值的是后者,而不是前者。
-
属性名与变量名
由于变量名与属性名并不一致,所以需要如下方式来改变,以实现如上的效果。<script type=”text/traceur”> var{name:person_name,age:person_age,id:person_id}={id:”007”,age:23,name:”zhangsan”}; console.log(person_name); //zhangsa console.log(person_age); //23 console.log(person.id); //007 </script>
-
对象解构指定默认值生效条件
默认值生效的条件是,对象的属性值严格等于undefined。
<script type=”text/traceur”> var {a=3} = {a= undefined}; console.log(a); //3 var {b=3} = { b=null }; console.log(b); // null </script>
-
现有对象的方法
<script type=”text/traceur”> console.log(Math.PI/6); let {sin,cos,tan} = Math; console.log(sin(Math.PI/6)); </script>
-
-
字符串的解构赋值
字符串被转换为一个类似数组的对象。
属性的解构赋值:由于字符串属性length,可以利用该属性进行解构赋值。const [a,b,c,d,e] = "hello"; console.log(a,b,c,d,e); //hello let {length:len} = "hello"; console.log(len); //5
-
数值和布尔值的解构赋值
解构赋值时,如果等号右边是数值和布尔值,则会先转为对象
注:解构赋值的规则是,只要等号右边的值不是对象或数组,就先将其转为对象。由于undefined和null无法转为对象,所以对它们进行解构赋值,都会报错。
-
函数参数的解构赋值
<script type=”text/traceur”> function fun( {x=0,y=0} = {} ){ return [x,y]; }; console.log(fun( {x:100,y:200} ) ); //[100,200] console.log(fun({x:100})); //[100,0] console.log(fun({})); //[0,0] </script>
-
解构赋值的用途
-
交换变量的值
<script type="text/traceur"> //ES5 console.log("ES5:"); var a=100; var b=200; console.log("交换前:"); console.log("a="+a); //100 console.log("b="+b); //200 var temp; temp=a; a=b; b=temp; console.log("交换后:"); console.log("a="+a); //200 console.log("b="+b); //100 //ES6 console.log("ES6:"); var x,y; console.log("交换前:"); console.log("a="+a); //100 console.log("b="+b); //200 //利用数组解构的方法进行交换 [x,y] = [y,x]; console.log("交换后:"); console.log("a="+a); //200 console.log("b="+b); //100 </script>
-
从函数中返回值
-
返回数组
<script type="text/traceur"> function fun(){ return [1,2,3]; }; var [x,y,z] = fun(); console.log(x); //1 console.log(y); //2 console.log(z); //3 </script>
-
返回对象
<script type="text/traceur"> function fun(){ return { id:"007", name:"zhao", age:20 }; }; var {id,name,age} = fun(); console.log(id); console.log(name); console.log(age); var {id:person_id,name:person_name,age:person_age} = fun(); console.log(person_id); console.log(person_name); console.log(person_age); </script>
-
-
函数参数定义
function fun(id,name,age){ }; fun({id:"007",name:"zhao",age:20}); //参数是一组无次序的值 function fun({x,y,z}){ }; fun({x:100,y:200,z:300});
-
函数参数默认值
<script type="text/traceur"> jQuery.ajax =function(url,{ async = true, beforeSend = function(){}, cache = true, global = true, }){ // }; </script>
-
遍历Map结构
<script type="text/traceur"> var map =new Map(); map.set("id","007"); map.set("name","Zhao"); console.log(map); //Map{id => "007",name =>"Zhao"} console.log(typeOf(map)); //Object for(let [key,value] of map){ console.log(key+"is" + value); } // id is 007 // name is Zhao //获取键名 for(let[key] of map){ console.log(key); } // id // name //获取键值 for(let[,value] of map){ console.log(value); } // 007 // Zhao </script>
-
提取JSON数据
<script type="text/traceur"> var jsonData ={ id:"007", name:"zhao", age:20, score:[100,90,89] }; console.log(jsonData); console.log("ES5"); console.log("Name"+jsonData.name); console.log("age"+jsonData.age); console.log("Chinese score"+jsonData.score[0]); console.log("Math score"+jsonData.score); console.log("ES6"); let{ id:number, name,age,score.score } =jsonData; console.log(number); console.log(name); console.log(age); conosle.log(score.Chinese); </script>
-
复制数组
(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);
箭头函数
ES6中可以使用 => 作为函数表达形式,极简风格,参数+ => +函数体。
var foo = function(){return 1;};
//等价于
let foo = () => 1;
let nums = [1,2,3,5,10];
let fives = [];
nums.forEach(v => {
if (v % 5 === 0)
fives.push(v);
});
console.log(fives); //[5,10]
//箭头函数中的 this 指的不是window,是对象本身。
//arguments不能使用this
const full = ({first,last}) => first + ' ' + last;
//等同于
function full(person){
return person.first + ' ' + person.last;
}
//箭头函数可以与变量解构结合使用。
-
注意点:
-
函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象。
-
不可以当作构造函数,也就是说,不可以使用new命令,否则会抛出一个错误。
-
不可以使用arguments对象,该对象在函数体内不存在。如果要用,可以用Rest参数代替。
-
不可以使用yield命令,因此箭头函数不能用作Generator函数。
-
-
箭头函数this指向问题
箭头函数里面的this,绑定定义时所在的作用域,而不是指向运行时所在的作用域。this指向的固定化,并不是因为箭头函数内部有绑定this的机制,实际原因是箭头函数根本没有自己的this,导致内部的this就是外层代码块的this。正是因为它没有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());
-
循环遍历整个对象
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
全局对象
全局对象:最顶层对象。
- 浏览器环境——window对象;
- Node.js——global对象
- Javascript——所有全局变量都是全局对象的属性
ES6中规定:
属于全局对象的属性:var、function声明的全局对象
不属于全局对象属性:let、const、class命令声明的全局对象
-
全局对象的属性
<script type=”text/traceur”> var varName =”varValue”; //浏览器环境 console.log(window.varName); //varValue //node.js环境 console.log(global.varName); //varValue //通用环境 console.log(this.varName); //varValue let letName =”letValue”; console.log(window.letName); //letValue || undefined—use strict console.log(this.letName); //letValue || undefined—use strict </script>
模块化
必须引入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))
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.isFinite(15); // true Number.isFinite(0.8); // true Number.isFinite(NaN); // false Number.isFinite(Infinity); // false Number.isFinite(-Infinity); // false Number.isFinite('foo'); // false Number.isFinite('15'); // false Number.isFinite(true); // false
-
Number.isNaN()用来检查一个值是否为NaN。
Number.isNaN(NaN) // true Number.isNaN(15) // false Number.isNaN('15') // false Number.isNaN(true) // false Number.isNaN(9/NaN) // true Number.isNaN('true'/0) // true Number.isNaN('true'/'true') // true
-
新方法与传统全局方法区别
它们与传统的全局方法isFinite()和isNaN()的区别在于:
- 传统方法先调用Number()将非数值的值转为数值,再进行判断
- 这两个新方法只对数值有效,Number.isFinite()对于非数值一律返回false, Number.isNaN()只有对于NaN才返回true,非NaN一律返回false。
isFinite(25) // true isFinite("25") // true Number.isFinite(25) // true Number.isFinite("25") // false isNaN(NaN) // true isNaN("NaN") // true Number.isNaN(NaN) // true Number.isNaN("NaN") // false Number.isNaN(1) // false
-
Number.parseInt(), Number.parseFloat()
ES6 将全局方法parseInt()和parseFloat(),移植到Number对象上面,行为完全保持不变。
// ES5的写法 parseInt('12.34') // 12 parseFloat('123.45#') // 123.45 // ES6的写法 Number.parseInt('12.34') // 12 Number.parseFloat('123.45#') // 123.45
这样做的目的,是逐步减少全局性方法,使得语言逐步模块化。
Number.parseInt === parseInt // true Number.parseFloat === parseFloat // true
-
Number.isInteger()用来判断一个数值是否为整数。
Number.isInteger(25) // true Number.isInteger(25.0) // true Number.isInteger(25.1) // false Number.isInteger("15") // false Number.isInteger(true) // false
-
Number.EPSILON
ES6在Number对象上面,新增一个极小的常量Number.EPSILON。
Number.EPSILON // 2.220446049250313e-16 Number.EPSILON.toFixed(20) // '0.00000000000000022204'
Math对象扩展
-
Math.trunc方法用于去除一个数的小数部分,返回整数部分。
Math.trunc(4.1) // 4 Math.trunc(4.9) // 4 Math.trunc(-4.1) // -4 Math.trunc(-4.9) // -4 Math.trunc(-0.1234) // -0
对于非数值,Math.trunc内部使用Number方法将其先转为数值。
Math.trunc('123.456') // 123
对于空值和无法截取整数的值,返回NaN。
Math.trunc(NaN); // NaN Math.trunc('foo'); // NaN Math.trunc(); // NaN
-
Math.sign方法用来判断一个数到底是正数、负数、还是零。对于非数值,会先将其转换为数值。
Math.sign(-5) // -1 Math.sign(5) // +1 Math.sign(0) // +0 Math.sign(-0) // -0 Math.sign(NaN) // NaN Math.sign('foo'); // NaN Math.sign(); // NaN
-
Math.imul方法返回两个数以32位带符号整数形式相乘的结果,返回的也是一个32位的带符号整数。
Math.imul(2, 4) // 8 Math.imul(-1, 8) // -8 Math.imul(-2, -2) // 4
-
Math.fround方法返回一个数的单精度浮点数形式。
Math.fround(0) // 0 Math.fround(1) // 1 Math.fround(1.337) // 1.3370000123977661 Math.fround(1.5) // 1.5 Math.fround(NaN) // NaN
数据结构(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和object比较
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 也可循环数组,但不能单独循环值
-
Map实例属性
- size 属性 size属性返回 Map 结构的成员总数
- set(key, value) set方法设置键名key对应的键值为value,然后返回整个 Map 结构。如果key已经 有值,则键值会被更新,否则就新生成该键。
- get(key) get方法读取key对应的键值,如果找不到key,返回undefined。
- has(key) has方法返回一个布尔值,表示某个键是否在当前 Map 对象之中。
- delete(key) delete方法删除某个键,返回true。如果删除失败,返回false。
- 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));
全局对象属性
全局对象:最顶层对象。
- 浏览器环境——window对象;
- Node.js——global对象
- Javascript——所有全局变量都是全局对象的属性
ES6中规定:
属于全局对象的属性:var、function声明的全局对象
不属于全局对象属性:let、const、class命令声明的全局对象
顶层对象
ES5中顶层对象是window,顶层对象的属性与全局变量是等价的
ES6规定,var 和 function 命令是全局变量,依旧是顶层对象的属性,但是let和const,class命令的全局变量不属于顶层对象的属性,也就是说es6开始,全局变量逐渐与顶层对象的属性脱钩
附录
ctrl+shift+方向键 使代码跳到上下行