简介
ECMAScript 6(以下简称ES6)是JavaScript语言的下一代标准,已经在2015年6月正式发布了。Mozilla公司将在这个标准的基础上,推出JavaScript 2.0。ECMA Script,JavaScript的语言标准。
作用
优点:提升JS编写大型的复杂应用程序的能力,升级加入了模块化的概念、细化和优化语法、封装了一些方法。
缺点:对浏览器存在兼容性问题
知识点
一:新增的声明变量
1、let
特点:声明的变量不会造成的全局的污染,因此新增一种块级作用域,存到临时性的死区
{
let num = 100;
console.log(num)
}
例如:
let a = 10;
{
console.log(a); //
let a = 20; //这时得a存到临时性的死区中
}
常见得面试题:
<body>
<button>0</button>
<button>1</button>
<button>2</button>
<button>3</button>
<button>4</button>
<button>5</button>
<script>
// i值的问题
var buttons = document.getElementsByTagName("button");
for(var i = 0;i < buttons.length;i++){
buttons[i].onclick = function(){
console.log(i);
}
}
解决办法一:ES6方法
for(let i = 0;i < buttons.length;i++){
buttons[i].onclick = function(){
console.log(i);
}
}
解决办法二:
(function(i){
for(var i = 0;i < buttons.length;i++){
buttons[i].onclick = function(){
console.log(i);
}
}
})(i)
</script>
</body>
2、const 常量
const定义的变量不可以修改,而且必须初始化,存到临时性的死区。
const b = 2;//正确
// const b;//错误,必须初始化
console.log('函数外const定义b:' + b);//有输出值
// b = 5;
// console.log('函数外修改const定义b:' + b);//无法输出
ES6新增了API:
1.is() ===
2.assign() 用于混合对象,带浅克隆
3…getOwnPropertyNames()
4.setPrototypeOf()
二:新增的字符串模板 ``
<script>
var day = "Hello";
var str = "world";
console.log(`${day}${str}`)
// `${表达式}字符串`
// 可以添加串
// 可以使用转义字符
// 可以嵌套
console.log(`${true?`Helloworld`:`My Gad`}`)
</script>
三:ES6解构
<script>
//1:对于对象
let obj = {
name : "wxw",
age : 21
}
let name,age;
({name,age} = obj);
console.log(name,age)
//2:
let {name , age} = obj;
console.log(name,age);
//3:
let {name : OName,age : OAge} = obj;
console.log(OName,OAge)
//对于数组
//1:
let arr = [1,3,5,7];
let [a,b,c,d] = arr;
console.log(a,b,c,d)
//2:
let {length} = arr;
console.log(length)
//3:
let {1:a,5:b,7:c,3:d} = arr;
var a = arr[1];
var b = arr[5]
var c = arr[7]
var d = arr[3]
console.log(a,b,c,d)
//4:
let arr = [1,2,3,{name:'wxw'}];
a : 1 b : 2 c : 3 name:wxw
let {0:a,1:b,2:c,3:{name:OName}} = arr;
console.log(a,b,c,oName)
//5
var OName = arr[3].name;
let [,,,{name : OName}] = arr;
console.log(OName)
</script>
四:…运算符
1、拓展运算符。
function myFunction(x, y, z) {
console.log(x + "" + y + "" + z);
}
var args = [0, 1, 2];
myFunction(...args);//...arr返回的并不是一个数组,而是各个数组的值
2、数组和对象的拷贝
数组:
var arr1 = [1,2,3];
var arr2 = [...arr1];
arr2.push(4);
console.log(arr1 === arr2); // false
console.log(arr1); // [1,2,3]
console.log(arr2);// [1,2,3,4]
对象:
var obj1 = {
a:1,
b:2
};
var obj2 = {...obj1};
console.log(obj2); //{ a:1, b:2}
console.log(obj1 === obj2);// false
提示:这是一个深拷贝,实际上, 展开语法和 Object.assign() 行为一致, 执行的都是浅拷贝(只遍历一层)。
3、构造字面量数组。
ES6之前只能组合使用 push, splice, concat 等方法,现在。。。
//代替Array.concat 函数
var arr1 = [1,2,3];
var arr2 = [4,5,...arr1];
console.log(arr2);
// [4,5,1,2,3]
代替Array.unshift 方法
var arr1 = [1,2,3];
var arr2 = [4,5,6];
var newarr = [...arr1,...arr2];
console.log(newarr );
// [1, 2, 3, 4, 5, 6]
newarr1= [...arr2,...arr1];
console.log(newarr1);
// [4, 5, 6, 1, 2, 3]
4、字符串转数组
var demo = "Hello"
var str = [...demo];
console.log(str);
// ["h", "e", "l", "l", "o"]
五:ES6 提供新内容,参数可以加默认值
function fun(a,b=1,c=2){
return a+b+c;
}
console.log( fun(undefined,undefined,30) );
console.log( fun(1,2,3) )
面试题:
<div id="container"></div>
<script>
//面试题
// 控制台输出几次test?
createElement(undefined,undefined,"sdfsdfsd")
createElement(undefined,undefined,"sdfsdfsd")
createElement(undefined,document.getElementById("container"),"sdfsdfsd")
// 2次 传递以后不会去看默认值
// 面试题
function test(a=b,b){ //Uncaught ReferenceError: Cannot access 'b' before initialization
at test
console.log(a,b)
}
test(undefined,2)
</script>
六:加判断instanceof,ES6之前没有办法完美解决
<script>
//面试点:new调用和直接调用出现的结果
function Person(firstName,lastName){
// 加判断 ES6之前没有办法完美解决
if(!(this instanceof Person)){
throw new Error("该函数必须使用new调用")
}
// 如果没有使用new 关键字调用函数,则返回undefined
// 如果使用了new调用,则返回的是函数的本身
if(new.target === undefined){
throw new Error("该函数必须使用new调用")
}
this.firstName = firstName;
this.lastName = lastName;
this.fullName = `${firstName} ${lastName}`
}
const p1 = new Person("张","三");
console.log(p1);
const p2 = Person("张","三");
console.log(p2)
// const p3 = Person.call(p1,"张","三")
// console.log(p3)
</script>
七:箭头函数
1、
x => x * x
//相当于
function (x) {
return x * x;
}
箭头函数相当于匿名函数,并且简化了函数定义。箭头函数有两种格式,一种像上面的,只包含一个表达式,连{ … }和return都省略掉了。还有一种可以包含多条语句,这时候就不能省略{ … }和return:
x => {
if (x > 0) {
return x * x;
}
else {
return - x * x;
}
}
如果参数不是一个,就需要用括号()括起来
// 两个参数:
(x, y) => x * x + y * y
// 无参数:
() => 3.14
// 可变参数:
(x, y, ...rest) => {
var i, sum = x + y;
for (i=0; i<rest.length; i++) {
sum += rest[i];
}
return sum;
}
如果要返回一个对象,就要注意,如果是单表达式,这么写的话会报错
// SyntaxError:
x => { foo: x }
因为和函数体的{ … }有语法冲突,所以要改为
x => ({ foo: x })
2、箭头函数的this指向问题,箭头函数和匿名函数有个明显的区别:箭头函数内部的this是词法作用域
ES6之前写法
面试点:this的指向
var obj = {
birthday: 1999,
getAge: function () {
var b = this.birthday; // 1990
var fn = function () {
return new Date().getFullYear() - this.birthday; // this指向window或undefined
};
return fn();
}
};
ES6之后写法
var obj = {
birthday: 1999,
getAge: function () {
var b = this.birthday; // 1990
var fn = () => new Date().getFullYear() - this.birthday; // this指向obj对象
return fn();
}
};
obj.getAge(); // 25
由于this在箭头函数中已经按照词法作用域绑定了,因此,用call()或者apply()调用箭头函数时,无法对this进行绑定,即传入的第一个参数被忽略。
var obj = {
birth: 1990,
getAge: function (year) {
var b = this.birth; // 1990
var fn = (y) => y - this.birth; // this.birth仍是1990
return fn.call({birth:2000}, year);
}
};
obj.getAge(2015); // 25
八:构造函数的新写法
class Person{
constructor(job,name,age,sex){
this.job = job;
this.name = name;
this.age = age;
this.sex = sex;
}
print(){
console.log('工作:',this.job)
console.log('姓名:',this.name)
console.log('年龄:',this.age)
console.log('性别:',this.sex)
}
}
const a = new Person("Web","wxw",18,"nan");
console.log(a)
a.print()
注意点:
1.类的声明不会被提升,和let const 一样,有临时性死区
2.类的所有代码全都是在严格模式中执行
3.类的所有方法都是不可枚举的
4.类的所有方法都无法当成构造函数直接使用
5.类的构造器必须使用new 来调用
setPrototypeOf() 设置某个对象的隐式原型 __ proto __
<script>
// 类的继承
function Amimal(name,age,sex){
this.name = name;
this.age = age;
this.sex = sex;
}
Amimal.prototype.print = function(){
console.log(`名字 : ${this.name}`)
console.log(`年龄 : ${this.age}`)
console.log(`性别 : ${this.sex}`)
}
function Dog(name,age,sex){
// 借助父类的构造函数
Amimal.call(this,name,age,sex);
}
Object.setPrototypeOf(Dog.prototype,Amimal.prototype)
const d = new Dog("来福",5,"公");
console.log(d);
d.print();
</script>
getOwnPropertyNames() 枚举的顺序,返回一个数组,枚举出来对象的属性
const obj = {
e : 1,
a : 2,
c : 3,
0 : 6,
5 : 7,
2 : 3
}
console.log(obj)
const arr = Object.getOwnPropertyNames(obj);
console.log(arr);
九:ES6新增对象的方法
1.属性简写
2.方法简写
3.计算属性名
const printName = "print";
const test = "job1"
class Person{
constructor(job,name,age,sex){
this[test] = job;
this.name = name;
this.age = age;
this.sex = sex;
}
[printName](){
console.log('工作:',this[test])
console.log('姓名:',this.name)
console.log('年龄:',this.age)
console.log('性别:',this.sex)
}
}
const a = new Person("程序猿","zhansan",30,"nan");
console.log(a)
a[printName]()
4;面向对象写法
function Elephant(){}
function Frige(){}
Frige.prototype.openDoor = function(){}
Frige.prototype.closeDoor = function(){}
Frige.prototype.join = function(){}
var frig = new Frige();
frig.openDoor()
var ele = new Elephant()
frig.join(ele)
frig.closeFrige()
小结:
等号表达式是典型的赋值形式,函数传参和for循环的变量都是特殊形式的赋值。解构的原理是赋值的两边具有相同的结构,就可以正确取出数组或对象里面的元素或属性值,省略了使用下标逐个赋值的麻烦。对于三个点号,三点放在形参或者等号左边为rest运算符; 放在实参或者等号右边为spread运算符,或者说,放在被赋值一方为rest运算符,放在赋值一方为扩展运算符。