一:Let
(1)Let定义块级作用域的变量,var定义的变量会提升。Let不会提升。如下。可以先用是undefined但是let在定义之前是不能用的。会报错Uncaught ReferenceError: letter is not defined(…)
console.log(color)
console.log(letter)
var color = ‘red‘;
let letter = ‘a‘
只要块级作用域内存在let命令,声明的变量不受外部影响。
var tmp = 123;
if (true) {
tmp = ‘abc‘; //tmp is not defined(…)
let tmp;
}
在代码块内,使用let命令声明变量之前,该变量都是不可用,称“暂时性死区”;
typeof x; //使用是在let声明之前x is not defined(…)
let x;
再如function bar(x = y, y = 1) {
return [x, y];
}
bar();// y is not defined(…)x的默认值等于y,此时y还没声明。
(2)通过var在块作用域中定义变量在外面可以访问,{}
通过let在块作用域中定义的变量,在外面不可以访问{}
if (true) {
// 块作用域里面都可以访问
var color = ‘red‘;
let letter = ‘a‘
console.log(color) //可以访问
console.log(letter) //可以访问
}
console.log(color) //可以访问
console.log(letter) //不能访问 letter is not defined(…)
(3)let保存变量
var arr = []
for (var i = 0; i < 5; i++) {
arr[i] = function () {
console.log(i, ‘iii‘)
}
}
arr[1]() //5,‘iii’
i是全局for循环外面也可以访问。For循环完之后i是5
var arr = [];
for (let j = 0; j < 5; j++) {
arr[j] = function () {
console.log(j, ‘jjjj‘)
}
}
arr[1](); // 1,’iii’
这个函数的时候,会找到这个块作用域,这个作用域中定义了块作用域变量j
console.log(i, j) j是外面无法访问的。
(4):不允许重复声明
function () {
let a = 10;
var a = 1;
}
//Uncaught SyntaxError: Unexpected token (
function () {
let a = 10;
let a = 1;
}
//Uncaught SyntaxError: Unexpected token (
2:const
(1)定义之后再也无法修改 (大写,下划线)
var PI = Math.PI;
PI = 3;
console.log(PI) //3
const PI = Math.PI
PI = 3;
console.log(PI) // 报错Assignment to constant variable.(…)
(2)在块作用域中定义一个常量 块作用域内访问有效。外面是访问不到的
if (true) {
const PIa = Math.PI
}
console.log(PIa) //PIa is not defined(…)
(3)必须先定义再使用
console.log(PIa) //Identifier ‘PI‘ has already been declared(…)
const PI = Math.PI;
二:字符串的拓展方法
(1)startsWith 判断字符串是否以某个字符开头
可以传两个参数{第一个参数表示要判断的字符串,第二个参数表示判断的位置(不传参数表示整个字符串)}
注:截取的是字符串后面的部分
返回值是布尔值:true或者false
eg:
var str = ‘这是一个美好的传说‘;
var result = str.startsWith(‘传说‘, 7);
//result 为true
(2)endsWith 判断字符串是否以某个字符结尾
可以传两个参数{第一个参数表示要判断的字符串,第二个参数表示判断的位置(不传参数表示整个字符串)}
注:截取的是字符串前面的部分
返回值是布尔值:true或者false
eg:
var str = ‘这是一个美好的传说‘;
var result = str.startsWith(‘个‘, 4);
//result 为true
(3)includes 判断字符串是否包含一个字符串
可以传两个参数{第一个参数表示要判断的字符串,第二个参数表示判断的位置(不传参数表示整个字符串)}
注:截取的是字符串后面的部分
返回值是布尔值:true或者false
eg:
var str = ‘这是一个美好的传说‘;
var result = str.includes (‘传说‘, 7);
//result 为true
(4)repeat 字符串的复写
参数是重复次数
eg:
let str = ‘这是一个美好的传说‘;
var result = str.repeat(2);
Console.log(result); //‘这是一个美好的传说这是一个美好的传说‘
(5)raw String的方法。获取原始字符串 里面转义字符不会被转义
注:标点符号 tab上面的那个``
var result = String.raw`你\n是一个\n好人`;
console.log(result)
// 你\n是一个\n好人
(6)模板字符串
语法是 ${书写表达式} ``支持多行字符串
eg:
var title = ‘你‘;
var str = `${title}是一个好人
啊`
console.log(str)
//你是一个好人
//啊
三:数值的拓展方法
(1)Number.isFinite() 用来检查一个数值是否为有限的(finite);
注:返回值为true表示有限 false表示无限
eg:
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.isFinite(false);
False
(2)Number.isNaN() 检查一个值是否是NaN
注:返回值为true表示是NaN false表示不是NaN
eg:
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
(3)Number.isInteger() 检查一个值是否是整数
注:返回值为true表示是整数(.0会转化为整数) false表示不是整数
eg:
Number.isInteger(25)
true
Number.isInteger(25.0)
true
Number.isInteger(25.1)
false
Number.isInteger("15")
false
Number.isInteger(true)
False
(4) Number.parseInt() Number.parseFloat() 用法同es5
Eg:
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
四:Math对象的扩展
(1)Math.trunc() 去除一个数的小数部分,返回整数部分
注:对于非数值,先用Number().转成数值。对于无法截取整数的返回NaN
Eg:
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(‘123.456‘)
123
Math.trunc(NaN);
NaN
Math.trunc(‘foo‘);
NaN
Math.trunc();
NaN
(2)Math.sign() 判断一个数字是正数,负数,还是0;
只有5种结果
NaN传递一个非数字
0 传递的是一个正零(0)
-0 传递的是一个负零(-0)
1 传递的是一个正数(有理数和正无穷)
-1 传递的是一个负数(有理数负无穷等)
Eg:
Math.sign(-5)
-1
Math.sign(5)
1
Math.sign(0)
0
Math.sign(-0)
-0
Math.sign(NaN)
NaN
Math.sign(‘foo‘);
NaN
五:数组对象的扩展
(1) Array.from()
类数组,可以像数组一样访问成员,但是不能使用数组的方法
该方法将类数组对象转化为真正的数组
注:可以传两个参数:
第一个参数是类数组对象
第二个参数是处理函数(value,index,类数组对象,作用域是window,返回值构成from方法处理的结果的一个新数组)
<ul>
<li>1 1 1</li>
<li>2 2 2</li>
<li>3 3 3</li>
</ul>
var lis = document.getElementsByTagName(‘li‘);
console.log(lis[1]) //222
但是不能对lis执行forEach方法(类数组不能使用数组的方法)
lis.forEach(function () {
console.log(111)
})
转化:
var result = Array.from(lis);
查看是不是数组:
console.log(Array.isArray(result)) //true
console.log(result instanceof Array) //true
console.log(result.constructor === Array) //true
console.log(Object.prototype.toString.call(result) === ‘[object Array]‘) //true
var result = Array.from(lis, function (value, index) {
//value dom
value.innerhtml += ‘修改内容‘ + index;
return value;
})
console.log(result)
Eg:
let arrayLike = {
‘0‘: ‘a‘,
‘1‘: ‘b‘,
‘2‘: ‘c‘,
length: 3
};
let arr2 = Array.from(arrayLike);
console.log(arr2)
// ["a", "b", "c"]
(2) Array.of() 将一组值转化为数组(不论传递几个参数,得到得都是一个数组。数组的成员就是参数的成员)
var arr = Array.of()
console.log(arr) //[]
var arr = Array.of(5)
console.log(arr) //[5]
var arr = Array.of(5,6)
console.log(arr) //[5,6]
var arr = Array.of([5,6])
console.log(arr) //[Array[2]]
之前:
var arr = new Array();
console.log(arr); //[] 空数组 arr.lenght=0;
var arr = new Array(5);
console.log(arr); //[] 空数组 arr.lenght=5;
如果参数是一个非数字参数,得到结果是一个包含一个参数成员的数组
var arr = new Array([1,2,3]);
console.log(arr); //[[1,2,3]]
var arr = new Array(‘abc’);
console.log(arr); //["abc"]
var arr = new Array(‘12’);
console.log(arr); //["12"]
console.log(arr); //[] 空数组 arr.lenght=5;
var arr = new Array(5,6); 传递两个或者更多参数得到一个数组,数组的成员就是传递参数
console.log(arr); //[5,6]
(3) 数组实例的方法copyWithin()
当前数组内部,将指定位置的成员复制到其他位置(会覆盖原有成员),然后返回当前数组。
接受三个参数:
target(必需):从该位置开始替换数据。
start(可选):从该位置开始读取数据,默认为0。如果为负值,表示倒数。
end(可选):到该位置前停止读取数据,默认等于数组长度。如果为负值,表示倒数。
Eg:
[1, 2, 3, 4, 5].copyWithin(0, 3)
//[4, 5, 3, 4, 5]
[1, 2, 3, 4, 5].copyWithin(0, 3, 4)
//[4, 2, 3, 4, 5]
[1, 2, 3, 4, 5].copyWithin(0, -2, -1) 4表示-2 5表示-1
//[4, 2, 3, 4, 5]
(4) 数组实例的方法find()和findIndex();
find()获取数组成员 返回值是一个成员值 非贪婪搜索找到就停止
findIndex();获取数组成员索引值 返回值是一个索引值 非贪婪搜索找到就停止
都可以接受一个回调函数作为处理函数(value,index,原数组)作用域是window.返回值是判断条件。
Eg:
var arr = [‘宋小宝‘, ‘小沈阳‘, ‘赵四‘, ‘刘能‘];
var result = arr.find(function (value, index, arr) {
return value.indexOf(‘小‘) > -1;
})
console.log(result); //宋小宝
[1, 4, -5, 10].find((n) => n < 0)
-5
[1, 5, 10, 15].find(function(value, index, arr) {
return value > 9;
})
10
[1, 5, 10, 15].findIndex(function(value, index, arr) {
return value > 9;
})
2
(5)数组实例的fill方法 使用给定值填充数组
用于空数组的初始化非常方便。数组中已有的元素,会被全部抹去。
(可以接受三个参数。填充值,起始位置,结束位置)
Eg:
[‘a‘, ‘b‘, ‘c‘].fill(7)
// [7, 7, 7]
new Array(3).fill(7)
// [7, 7, 7]
[‘a‘, ‘b‘, ‘c‘].fill(7, 1, 2) 从1开始到2之前
//["a", 7, "c"]
[‘a‘, ‘b‘, ‘c‘].fill(7, 1, 3)
// ["a", 7, 7]
(6)数组实例的 includes()返回一个布尔值,表示某个数组是否包含给定的值,与字符串的includes方法类似。
可以接受第二个参数,表示搜索的起始位置,默认为0。如果第二个参数为负数,则表示倒数的位置,如果这时它大于数组长度(比如第二个参数为-4,但数组长度为3),则会重置为从0开始。
Eg:
[1, 2, 3].includes(2)
// true
[1, 2, 3].includes(4)
// false
[1, 2, NaN].includes(NaN)
// True
[1, 2, 3].includes(3, 3);
// false
[1, 2, 3].includes(3, -1);
// True
[1, 2, 3].includes(3, -4);
// true
(7)数组实例的entries(),keys()和values()
这个三个方法返回的都是迭代器对象,可以用for...of循环进行遍历
或者手动调用遍历器对象的next方法,进行遍历。
Keys 表示获取数组中所有成员的索引值(键名)
Values 表示获取数组中所有成员的值(键值)
Entries 表示获取数组中所有成员与索引值组成数组对(键值对)
Eg:
var colors = [‘red‘, ‘green‘, ‘blue‘];
var keys = colors.keys();
console.log(keys); 迭代器对象
for (var index of keys) {
console.log(index)
}
// 0
// 1
// 2
var colors = [‘red‘, ‘green‘, ‘blue‘];
var entries = colors.entries();
for (var entry of entries) {
console.log(entry)
}
// [0, "red"]
// [1, "green"]
// [2, "blue"]
六:对象的拓展
(1) 如果属性的名称跟设置的变量名称相同,这个名称可以省略
在属性名称中可以使用表达式(表达式一定要用[]括起来)
如果方法的名称跟定义的方法名称相同,我们可以省略function(在定义类的时候一样定义方法)
Eg:
var color = ‘red‘;
var title = ‘爱‘;
Es5:
var obj = {
color: color,
title: title
}
Es6:
function f(x, y) {
return {x, y};
}
f(1, 2)
// Object {x: 1, y: 2}
var obj = {color, title, num: 100}
// Object {color: "red", title: "爱", num: 100}
var color = ‘red‘;
var title = ‘爱‘;
var obj = {
// 定义一个redgreen的属性
[color + ‘green‘]: 200
}
console.log(obj);
// Object {redgreen: 200}
var color = ‘red‘;
var title = ‘爱‘;
var obj = {
color,
getColor() {
return this.color;
}
}
console.log(obj)
console.log(obj.getColor())
// Object {color: "red"}
// red
function getPoint() {
var x = 1;
var y = 10;
return {x, y};
}
getPoint()
// Object {x: 1, y: 10}
(2)Object.is() 判断两个数据是不是同一个数据
ES5比较两个值是否相等,只有两个运算符:相等运算符(==)和严格相等运算符(===)。它们都有缺点,前者会自动转换数据类型,后者的NaN不等于自身,以及+0等于-0。
+0 === -0
//true
NaN === NaN
//false
Object.is(‘foo‘, ‘foo‘)
//true
Object.is({}, {})
//false
Object.is(+0, -0)
//false
Object.is(NaN, NaN)
//true
(3)Object.assign()
将源对象(source)的所有可枚举属性,复制到目标对象(target)
第一个参数表示源对象(source),后面的参数表示目标对象
Object.assign(obj1, obj2, obj3)
注:是一个浅复制,只是对对象上的属性做简单copy而已
源对象中如果有相同的属性会被覆盖,或多个源对象有同名属性,则后面的属性会覆盖前面的属性。
Eg:
var target = { a: 1 };
var source1 = { b: 2 };
var source2 = { c: 3 };
Object.assign(target, source1, source2);
console.log(target);
// Object {a: 1, b: 2, c: 3}
var target = { a: 1, b: 1 };
var source1 = { b: 2, c: 2 };
var source2 = { c: 3 };
Object.assign(target, source1, source2);
console.log(target)
// Object {a: 1, b: 2, c: 3}
只有一个参数,Object.assign会直接返回该参数。
var obj = {a: 1};
Object.assign(obj) === obj
//true
(4)Symbol对象
ES6 引入了一种新的原始数据类型Symbol,表示独一无二的值。它是 javascript 语言的第七种数据类型,前六种是:undefined、null、布尔值(Boolean)、字符串(String)、数值(Number)、对象(Object)。
symbol函数前不能使用new命令,否则会报错。因为生成的 Symbol 是一个原始类型的值,不是对象。
Eg:
let s = Symbol();
typeof s
// "symbol"
let s = new Symbol();
typeof s
// Identifier ‘s‘ has already been declared at
var s1 = Symbol(‘foo‘);
var s2 = Symbol(‘bar‘);
s1
// Symbol(foo)
s2
// Symbol(bar)
s1.toString()
// "Symbol(foo)"
s2.toString()
// "Symbol(bar)"
Symbol函数的参数只是表示对当前 Symbol 值的描述,因此相同参数的Symbol函数的返回值是不相等的。
var s1 = Symbol();
var s2 = Symbol();
s1 === s2
//false
var s1 = Symbol(‘foo‘);
var s2 = Symbol(‘foo‘);
s1 === s2
//false
用途:通常在定义对象属性的时候使用它,(此时对象的属性名就是一个独一无二的字符串),是为了防止重复属性被覆盖的。
var obj = {
color: ‘red‘,
color: ‘green‘
}
console.log(obj)
// Object {color: "green"}
var key1 = Symbol(‘color‘);
var key2 = Symbol(‘color‘);
console.log(key1) //Symbol(color)
console.log(key2) //Symbol(color)
console.log(key2 == key1) false
var obj = {
[key1]: ‘red‘,
[key2]: ‘green‘
}
console.log(obj[key1])
// red
七:函数的拓展
(1)在ES6之前,不能直接为函数的参数指定默认值
function log(x, y) {
y = y || ‘World‘;
console.log(x, y);
}
log(‘Hello‘)
//Hello World
log(‘Hello‘, ‘China‘)
//Hello China
log(‘Hello‘, ‘‘)
//Hello World
上面检查函数log的参数y有没有赋值,如果没有,则指定默认值为World。这种写法的缺点在于,如果参数y赋值了,但是对应的布尔值为false,则该赋值不起作用。就像上面代码的最后一行,参数y等于空字符,结果被改为默认值。
解决办法:
if (typeof y === ‘undefined‘) {
y = ‘World‘;
}
先判断再赋值
ES6可以为函数设置默认值,直接写在参数定义的后面
function say (msg = ‘hello‘) {
console.log(msg)
}
say ()
// hello
function log(x, y = ‘World‘) {
console.log(x, y);
}
log(‘Hello‘)
//Hello World
log(‘Hello‘, ‘China‘)
//Hello China
log(‘Hello‘, ‘‘)
//Hello
function Point(x = 0, y = 0) {
this.x = x;
this.y = y;
}
var p = new Point();
Log(p)
//Point {x: 0, y: 0}
如下参数变量是默认声明的,在函数体中,不能用let或const再次声明,否则会报错。
function foo(x = 5) {
let x = 1;
}
//Identifier ‘x‘ has already been declared
function foo(x = 5) {
const x = 2;
}
//Identifier ‘x‘ has already been declared
(2)Rest参数即剩余参数
用于获取函数的多余参数,这样就不需要使用arguments对象了。rest 参数搭配的变量是一个数组,该变量将多余的参数放入数组中。
...语法可以实现对剩余参数的定义
注:在箭头函数中不能使用arguments
function add(...values) {
let sum = 0;
for (var val of values) {
sum += val;
}
return sum;
}
add(2, 5, 3)
// 10
function push(array, ...items) {
items.forEach(function(item) {
array.push(item);
console.log(item);
});
}
var a = [];
push(a, 1, 2, 3)
// 1
// 2
// 3
rest 参数之后不能再有其他参数(即只能是最后一个参数),否则会报错。
function f(a, ...b, c) {
// ...
}
//Rest parameter must be last formal parameter