一,变量声明:Let
与const
ES6推荐使用Let
来声明变量,Let
提供块作用域(block-scoping),这会比var
提供的以函数为作用域有更加精细化的控制。请看下面例题
问:在下面程序中,控制台打印的最终结果?
function fn() {
var arr = [];
for (var i = 0; i < 5; i++) {
arr.push(function(){
return console.log(i);
})
}
return arr;
}
for (let i = 0; i < 5; i++) {
fn()[i]()
}
复制代码
你可能会误以为结果是[0,1,2,3,4]
,但实际却是[5,5,5,5,5]
用var
来定义一个变量,JavaScript
在预先编译的时候会将变量提升至函数的顶部,经过5个for
循环,arr
里面的i
会指向同一个i
,此时函数中的i
已经是5,所以最终结果也就是5了。
下面把for
循环的var
改为let
:
function fn() {
var arr = [];
for (let i = 0; i < 5; i++) {
arr.push(function(){
return console.log(i);
})
}
return arr;
}
for (let i = 0; i < 5; i++) {
fn()[i]()
}
复制代码
结果输出[0,1,2,3,4]
,因为let
拥有块作用域,所以使用let
声明的变量i
不会被提升到函数顶部,i
的作用域在for
循环, 就会每次循环有独立的值。
如果你想定义一个常量,请使用ES6里的const
,const
声明的变量是完全不可更改的。
const PI = 3.14;
PI = 1;
复制代码
结果是直接报错 Uncaught TypeError: Assignment to constant variable. at <anonymous>:3:4
关于let
与const
有几个点需要注意
- let 关键词声明的变量不具备变量提升(hoisting)特性
- let 和 const 声明只在最靠近的一个块中(花括号内)有效
- 当使用常量 const 声明时,请使用大写变量,如:CAPITAL_CASING
- const 在声明时必须被赋值
二, 模板字符串
在ES6之前我们往往用+
来处理模板字符串
var str = 'I' + 'Have' + Num + 'Apple'
复制代码
而在ES6中基本的字符串格式化,将表达式嵌入字符串中进行拼接,用${}来界定;ES6反引号(``)直接搞定
var str = `I Have ${Num} Apple`
复制代码
三, 箭头函数(Arrow Functions)
ES6中,箭头函数是函数的一种简写形式 () = >
箭头函数最直观的三个特点
- 不需要
function
关键字来创建函数- 省略
return
关键字- 当你的函数有且仅有一个参数的时候,是可以省略掉括号的。当你函数返回有且仅有一个表达式的时候可以省略'{}' 和 'return';
//ES5
var fn = function(x){
return x
}
//ES6
var fn = (x) = >{
return x
}
//ES6简写
var fn = x => x
复制代码
四, 对象的遍历:for...in
//定义一个对象
var Apple = {
color: "red",
weight: "50g",
kind:function(){
console.log("HongFuShi")
}
}
//用for...in遍历对象
for(let item in Apple){
console.log(Apple[item])
}
复制代码
五,ES6中的类class
ES6 中支持 class 语法,不过,ES6的class不是新的对象继承模型,它只是原型链的语法糖表现形式。
用class
创建对象的格式:
class 类名{
constructor(参数){
this.属性 = 参数;
}
method(){
// 对象中简写方法,省略了function。不要与箭头函数搞混了
}
}
复制代码
- 注意:ES6 中支持
class
语法,不过,ES6的class
不是新的对象继承模型,它只是原型链的语法糖表现形式- ES6 中支持
class
语法,不过,ES6的class
不是新的对象继承模型,它只是原型链的语法糖表现形式。- 方法和方法之间没有逗号。不是键值对
在ES5中,我们创建一个类通常如下:
//创建一个构造函数
function Apple (color,weight) {
this.color = color;
this.weight = weight;
}
//向函数原型写入方法
Apple.prototype.getkind = function(){
console.log('HongFuShi');
}
//创建新对象,并调用方法
var Apple = new Apple("red","50g");
console.log(Apple);
Apple.getkind();
复制代码
在ES6中我们可以用class
来声明一个类
//创建一个类
class Apple {
//构造器
constructor(color, weight) {
this.color = color;
this.weight = weight;
}
//类方法
getkind(){
console.log('HongFuShi');
}
}
//创建新对象并调用属性方法
var new_Apple = new Apple("red","50g");
console.log(new_Apple);
Apple1.getkind()
复制代码
- 这里值得注意的是你
new
的对象名称不能与类的名称重复。
六,ES6里 类class
中的继承Extends
在ES5中我们继承属性是这样写的:
//创建Apple构造函数
function Apple (color,weight) {
this.color = color;
this.weight = weight;
}
//函数原型添加方法
Apple.prototype.getkind = function(){
console.log('HongFuShi');
}
//创建Smell_Apple构造函数
function Smell_Apple (color,weight,smell) {
Apple.call(this,color,weight); //利用call改变this指向,达到属性继承
this.smell = smell;
}
//浅拷贝继承方法
for (const key in Apple.prototype) {
Smell_Apple.prototype[key] = Apple.prototype[key]
}
Smell_Apple.prototype.show = function(){
console.log(`苹果的颜色是${this.color},重量是${this.weight},
味道${this.smell}`);
}
//调用继承后的构造函数
var new_Apple = new Smell_Apple("red","50g","good")
console.log(new_Apple);
new_Apple.getkind()
new_Apple.show();
复制代码
在ES6中我们可以使用Extends
来继承:
//创建一个父类
class Apple {
constructor(color, weight) {
this.color = color;
this.weight = weight;
}
getkind(){
console.log('HongFuShi');
}
}
//子类继承父类
class Smell_Apple extends Apple{
constructor(color,weight,smell) {
super(color,weight)
this.smell = smell;
}
show(){
console.log(`苹果的颜色是${this.color},重量是${this.weight},
味道${this.smell}`);
}
}
let new_Apple = new Smell_Apple("red","50g","good");
console.log(new_Apple);
复制代码
七,ES6中新增的两种集合
我们在以往的ES版本中了解到了两种集合,arr
与object
; ES6中我们又学到了两种新增的集合set
和map
;
Set :
set
和数组差不多,也是一种集合,区别在于:它里面的值都是唯一的,没有重复的。
//创建一个set
var arr = new Set([1,true,'hello',null,undefined,{name:'Apple'},function(){}])
console.log(arr) //Set { 1, true, 'hello', null, undefined, { name: 'Apple' }, [Function] }
复制代码
- 注意:创建
set
时,传多个参数时要用[]
进行,单个可以用add()
进行传参
var arr = new Set();
arr.add(1)
arr.add(true)
...
arr.add(function(){})
复制代码
遍历set
有两种方式:
1 , forEach
var arr = new Set([1,true,'hello',null,undefined,{name:'Apple'},function(){}])
arr.forEach(vul => {
console.log(vul);
});
复制代码
2 , for of
var arr = new Set([1,true,'hello',null,undefined,{name:'Apple'},function(){}])
for(let vul of arr){
console.log(vul);
}
复制代码
- 注意:
1,set不是1数组,是一个像对象的伪数组
2,set中的值是唯一的,数组中的值是不唯一的,不会重复
var arr = new Set([1,1,1,2,2,2])
console.log(arr);//输出Set { 1, 2 }
//利用以上特性我们可以很轻易的做到数组去重
var arr_one = [1,1,1,2,2,2]
var set_one = [...(new Set(arr_one))]
console.log(set_one) //输出[1,2]
复制代码
Map :
它类似于对象,里面存放也是键值对,区别在于:对象中的键名只能是字符串,如果使用map,它里面的键可以是任意值。
//创建一个Map
var M = new Map([
['a','Hello'],
['1','123']
]);
复制代码
使用set
进行添加
var M = new Map();
M.set(false,'abc') //Map { false => 'abc' }
复制代码
通过get
键来获取
var M = new Map([
['a','Hello'],
['1','123']
]);
M.get('a') // Hello
M.get('1') // 123
复制代码
八 , 字符串的扩展
1,模板字符串
2,其它的方法
(1) trim
去除字符串空格的。
trim
左右空格都是去掉trimLeft
左空格去掉trimRight
右空格去掉
let str = ' a ab abc ';
console.log(str);
console.log(str.trim());
console.log(str.trimLeft());
console.log(str.trimReft());
复制代码
(2) , repeat
顾名思义就是重复,可以把一个参数复制多份
let str = '123';
console.log(str.repeat(2)); //123123
console.log(str.repeat(3)); //123123123
复制代码
(3) , includes
查找当前字符串有没有指定的字符
let str = '123 abc';
console.log(str.includes('1'));//true
console.log(str.includes('a'));//true
复制代码
(4) , startWith
判断当前字符串是不是以指定字符开始的 endsWidth
与之相反
let str = '123 abc';
console.log(str.startsWith('123')); //true
console.log(str.startsWith('123a')); //false
console.log(str.endsWith('abc')); //true
console.log(str.endsWith('3abc')); //false
复制代码
(5) , padStart
与padEnd
,两个相反,可接受两个参数,第一个参数是预期的字符串长度,第二个参数是当字符串与预期长度不符时所填充的字符
let str = '123 abc';
console.log(str.padStart(10,'*'));//***123 abc
console.log(str.padEnd(10,'*')); //123 abc***
复制代码
九 , 严格模式
以下是严格模式中需要注意的用法,这里需要强调的是:ES6 的 class 和 模块内都是默认的严格模式。其实,js 开发也会逐步走向严格模式,这应该是个趋势。
s添加了保留字 protected,static 和 interface
1,在严格模式下,不可以用with()
(function(){
//非严格模式
var a = {name: "Bob"};
with(a){
name = "Lily";
}
console.log(a.name); //Lily
})();
(function(){
"use strict"; //严格模式
var a = {name: "Bob"}, b = {};
with(a, b){ //SyntaxError: Strict mode code may not include a with statement
name = "Lily";
}
console.log(a.name);
})();
复制代码
2,在严格模式下,变量必须显示声明(var/let/const)
(function(){
//非严格模式
a = 10;
console.log(a); //10
})();
(function(){
"use strict"; //严格模式
b = 10; //ReferenceError: b is not defined
console.log(b);
})();
复制代码
3,在严格模式下,this默认是undefined
(function(){
//非严格模式
console.log(this); //window
})();
(function(){
"use strict"; //严格模式
console.log(this); //undefined
})();
复制代码
4,在严格模式下,为只读变量和不可扩展对象赋值会报错, 而不是静默失败
(function(){
//非严格模式
var o = {
name: "Lily"
};
Object.freeze(o);
o.name = "Bob";
o.age = 20;
console.log(o); //Object {name: "Bob"}
})();
(function(){
"use strict"; //严格模式
var o = {
name: "Lily"
};
Object.freeze(o);
o.name = "Bob"; //TypeError: Cannot assign to read only property 'name' of object '#<Object>'
o.age = 20; //TypeError: Can't add property age, object is not extensible
console.log(o);
})();
复制代码
5,在严格模式下,不可以在eval参数中定义变量和函数
(function(){
//非严格模式
var str1 = "var name='Lily';";
var str2 = "function fun1(){console.log('hello');}";
eval(str1); //这个name定义在了全局,而不是函数内
eval(str2);
console.log(name); //Lily
fun1(); //hello
})();
(function(){
"use strict"; //严格模式
var str1 = "var alias='Lily';";
var str2 = "function fun2(){console.log('hello');}";
eval(str1);
eval(str2);
eval("name = 'Bob'"); //修改全局变量name
console.log(name); //Bob
console.log(alias); //ReferenceError: alias is not defined
fun2(); //ReferenceError: fun is not defined
})();
复制代码
6,在严格模式下,有名参数是arguments参数的静态副本,而非引用。
(function(){
//非严格模式
var name = "Bob";
test(name);
function test(alias){
alias = "Lily";
console.log(alias); //Lily
console.log(arguments[0]); //Lily
}
})();
(function(){
"use strict"; //严格模式
var name = "Bob";
test(name);
function test(alias){
alias = "Lily";
console.log(alias); //Lily
console.log(arguments[0]); //Bob
}
})();
复制代码
7 ,在严格模式下,用delete删除var声明的变量和不可配置属性时抛出异常,而不是静默失败(返回false)
(function(){
//非严格模式
var a = 10;
var fun = function(){console.log("fun called");};
var o = Object.defineProperty({}, "name", {
value: "Bob"
}); //默认即不可配置
delete a; //false
console.log(a); //10
delete fun; //false
fun(); //fun called
delete o.name; //false
console.log(o.name); //Bob
//删除一个不存在的变量
delete no; //false
})();
(function(){
"use strict"; //严格模式
var a = 10;
var fun = function(){console.log("fun called");};
var o = Object.defineProperty({}, "name", {
value: "Bob"
}); //默认即不可配置
//delete a; //SyntaxError: Delete of an unqualified identifier in strict mode.
console.log(a);
delete fun; //SyntaxError: Delete of an unqualified identifier in strict mode.
fun();
delete o.name; //SyntaxError: Delete of an unqualified identifier in strict mode.
console.log(o.name);
//删除一个不存在的变量
delete no; //SyntaxError: Delete of an unqualified identifier in strict mode.
})();
复制代码
8,在严格模式下,arguments和eval是关键字,不能被修改
(function(){
//非严格模式
eval = 10;
eval("console.log('hello');"); //TypeError: eval is not a function
(function(){
arguments = 20;
console.log(arguments); //20
}());
})();
(function(){
"use strict"; //严格模式
eval = 10; //SyntaxError: Unexpected eval or arguments in strict mode
eval("console.log('hello');");
(function(){
arguments =20; //SyntaxError: Unexpected eval or arguments in strict mode
console.log(arguments);
}());
})();
复制代码
9,在严格模式下,不可以用8进制
(function(){
//非严格模式
console.log(070); //56 (因浏览器而异)
})();
(function(){
"use strict"; //严格模式
console.log(070); //SyntaxError: Octal literals are not allowed in strict mode.
})();
复制代码
10,在严格模式下,函数的形参不可以同名
(function(){
//非严格模式
var one = 1;
var two = 2;
fun(one, two); //2
function fun(a,a){
console.log(a);
}
})();
(function(){
"use strict"; //严格模式
var one = 1;
var two = 2;
fun(one, two);
function fun(a,a){ //SyntaxError: Duplicate parameter name not allowed in this context
console.log(a);
}
})();
复制代码
11,在严格模式下,不可以使用caller和arguments的属性,会报错
(function(){
//非严格模式
A();
function A(){
B();
}
function B(){
console.log(B.caller); //function A(){ B(); }
console.log(arguments.callee); //function B(){ console.log(B.caller); console.log(arguments.callee); }
}
})();
(function(){
"use strict"; //严格模式
A();
function A(){
B();
}
function B(){
console.log(B.caller); //TypeError: 'caller' and 'arguments' are restricted function properties and cannot be accessed in this context.
console.log(arguments.callee); //TypeError: 'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the arguments objects for calls to them
}
复制代码
以上就是我目前接触到的ES6新增特性.