es6的新增特性
箭头函数的问题在我面试的时候也遇到了
es6新增的特性:
1.Let和const关键字:var支持变量提升 let不支持
let只能声明一次 var可以重新声明
let声明的变量可以改变,值和类型都可以改变,没有限制。
let a = []
a = [1,3,5] //没问题
a = 'sdsdsdsd'
const声明的变量不得改变值,这意味着,const一旦声明变量,就必须立即初始化,不能留到以后赋值。
但是数组 对象 可以修改内部的值 因为 不能修改是因为一旦修改就改变了变量指向的地址 但是修改内部的值 地址是不会变得 所以可以修改
const names = [];
names = [1,2,3] //出错,因为变量names指向的地址不能发生改变,应始终指向[]所在的地址!!![1,2,3]与[]不是同一个地址
//不会报错,因为names指向的地址不变,改变的只是内部数据
const names = [];
names[0] = 1
names[1] = 2
names[2] = 3
如果想让定义的对象或数组的内部数据也不能够修改和改变,可以使用object.freeze(names)进行冻结,这样为对象添加新属性就不起作用。
var constantize = (obj) => {
Object.freeze(obj);
Object.keys(obj).forEach( (key) => {
if ( typeof obj[key] === 'object' ) {
constantize( obj[key] );
}
});
};
2.for(let itemof Arr)可以达到和for(vari=0;i<Arr.length;i++)原来的同样得效果。
在这里插入代码片
3.字符串模板:在ES6之前,将字符串连接到一起的方法是+或者concat()方法,
而字符串模板:
let message = `${student.name} please see ${teacher.name} in ${teacher.room} to pick up your report card.`;
4.’… ’ : 展开运算符
展开运算符(用三个连续的点 (…) 表示)是 ES6 中的新概念,使你能够将字面量对象展开为多个元素.
const books = ["Don Quixote", "The Hobbit", "Alice in Wonderland", "Tale of Two Cities"];
console.log(...books);
使用展开符来结合数组
const fruits = ["apples", "bananas", "pears"];
const vegetables = ["corn", "potatoes", "carrots"];
const produce = [...fruits,...vegetables];
console.log(produce);
Prints: [“apples”, “bananas”, “pears”, “corn”, “potatoes”, “carrots”]
5.箭头函数:
在没有箭头函数之前是这样写的:
const upperizedNames = ['Farrin', 'Kagure', 'Asser'].map(function(name) {
return name.toUpperCase();
});
有了箭头函数之后:
const upperizedNames = ['Farrin', 'Kagure', 'Asser'].map(
name => name.toUpperCase()
);
通函数可以是函数声明或者函数表达式, 但是箭头函数始终都是表达式, 全程是箭头函数表达式, 因此因此仅在表达式有效时才能使用,包括:
存储在变量中、当做参数传递给函数、存储在对象的属性中。
const greet = name => `Hello ${name}!`;
greet('Asser');
如果函数的参数只有一个,不需要使用()包起来,但是只有一个或者多个, 则必须需要将参数列表放在圆括号内:
// 空参数列表需要括号
const sayHi = () => console.log('Hello Udacity Student!');
// 多个参数需要括号
const orderIceCream = (flavor, cone) => console.log(`Here's your ${flavor} ice cream in a ${cone} cone.`);
orderIceCream('chocolate', 'waffle');
但是如果箭头函数的主体内需要多行代码, 则需要使用常规主体语法:
它将函数主体放在花括号内,需要使用 return 语句来返回内容
const upperizedNames = ['Farrin', 'Kagure', 'Asser'].map( name => {
name = name.toUpperCase();
return `${name} has ${name.length} characters in their name`;
});
var constantize = (obj) => {
Object.freeze(obj);
Object.keys(obj).forEach( (key) => {
if ( typeof obj[key] === 'object' ) {
constantize( obj[key] );
}
});
};
1.去掉function,没有参数或者多个参数时需要加括号(),多个参数时使用逗号分隔,一个参数时括号可以省略。
const numbers=[1,2,3,4,5];
const double=numbers.map(function(number){
return number*2
})
console.log(double);
//[2, 4, 6, 8, 10]
使用箭头函数改写:
let numbers1=[1,2,3,4,5];
let double1=numbers.map((number)=>{
return number*2
})
console.log(double1);
//[2, 4, 6, 8, 10]
2.隐士返回,如 下面的代码可以去掉return,代码移到一行,减少代码量。
let numbers1=[1,2,3,4,5];
let double1=numbers.map((number)=>number*2)
console.log(double1);
//[2, 4, 6, 8, 10]
let sum = (...args) => args.reduce((a, b) => a + b, 0)
let getObj = () => ({ foo: 'hello', bar: 'world' })
3.解决了this的指向问题,原生的写法this指向的是调用者,箭头函数this绑定的是定义时的那个对象。
箭头函数的this绑定看的是this所在的函数定义在哪个对象下,绑定到哪个对象则this就指向哪个对象
如果有对象嵌套的情况,则this绑定到最近的一层对象上
//定义一个对象
var obj = {
x:100,//属性x
show(){//延迟500毫秒,输出x的值
setTimeout( //匿名函数 function(){console.log(this.x);}, 500 );
}
};
obj.show();//打印结果:undefined
为什么结果打印是undefined呢,问题出在了this上,当代码执行到了setTimeout( )的时候,此时的this已经变成了window对象(setTimeout( )是window对象的方法),已经不再是obj对象了,所以我们用this.x获取的时候,获取的不是obj.x的值,而是window.x的值,再加上window上没有定义属性x,所以得到的结果就是:undefined。
换成箭头函数就对了。
//定义一个对象
var obj = {
x:100,//属性x
show(){
//延迟500毫秒,输出x的值
setTimeout(
//不同处:箭头函数
() => { console.log(this.x)},
500
);
}
};
obj.show();//打印结果:100
当定义obj的show( )方法的时候,我们在箭头函数编写this.x,此时的this是指的obj,所以this.x指的是obj.x。而在show()被调用的时候,this依然指向的是被定义时候所指向的对象,也就是obj对象,故打印出:100。
解决方法:
let self = this;
//定义一个对象
var obj = {
x:100,//属性x
show(){//延迟500毫秒,输出x的值
let self = this;
setTimeout( //匿名函数 function(){console.log(self.x);}, 500 );
}
};
obj.show();//打印结果:undefined
也可以使用bind、call和apply等方法来实现这一点。
那么总结下什么时候我们不能使用箭头函数:
(1)做为构造函数的时候不能使用箭头函数 因为 箭头函数没有prototype 原型。不能和new
let Person = function(name, height) {
this.name = name
this.height = height
}
Person.prototype.hello = function() {
console.log('Hi, my name is ' + this.name)
}
let alice = new Person('Alice', 1.7)
alice.hello() // Hi, my name is Alice
(2)真正需要this的时候如给元素绑定click事件的 时候,执行的回调函数不能使用箭头函数。
(3)我们需要使用arguments对象的时候不能使箭头函数。箭头函数中没有arguments对象。
6.symbol
ES6 引入了一种新的原始数据类型Symbol,表示独一无二的值
ES5 的对象属性名都是字符串,这容易造成属性名的冲突.
let s = Symbol();
typeof s // "symbol"
这样就从根本上防止属性名的冲突。这就是 ES6 引入Symbol的原因。
let s1 = Symbol('foo');
let s2 = Symbol('bar');
s1 // Symbol(foo)
s2 // Symbol(bar)
s1.toString() // "Symbol(foo)"
s2.toString() // "Symbol(bar)"
上面代码中,s1和s2是两个 Symbol 值。如果不加参数,它们在控制台的输出都是Symbol(),不利于区分。有了参数以后,就等于为它们加上了描述,输出的时候就能够分清,到底是哪一个值。
s1和s2都是Symbol函数 参数相同 返回值 不相同 ==false ===false
let s1 = Symbol();
let s2 = Symbol();
s1 === s2 // false
// 有参数的情况
let s1 = Symbol('foo');
let s2 = Symbol('foo');
s1 === s2 // false
注意:symbol可以打印toString 但是不能转换成数字Number 可以转成Boolean为true
Symbol值作为对象属性名时,不能用点运算符。 可以有以下两种写法
let sym = Symbol();
// 第一种写法
let a = {};
a[sym] = "hello";
// 第二种写法
let b = {
[sym]: "hello"
};
symbol还可以定义一些常量
const log = {};
log.levels = {
DEBUG: Symbol('debug'),
INFO: Symbol('info'),
WARN: Symbol('warn'),
SUCCESS: Symbol('success')
};
console.log(log.levels.DEBUG, 'debug message')
7.set
使用Set实现数组去重
let guaiguai = [1,2,3,4,4,5,5,{a:45,name:'sss'}]
let arr = []
arr = new Set(guaiguai)
var a = [1,3,4,5,6,5,{a:'suyan'}];
function uniq(arr){return Array.from(new Set(arr))}
uniq(a);
8.Map
9.数组的复制
arr2=Array.from(arr1)
10.新增加的函数:find findIndex Array.from includes