简单做个笔记,供自己以后查阅。
1. let和const
块级作用域:
Es5的时候只存在两者作用域:全局作用域和函数作用域,Es6引入块级作用域。
function f1() {
let n = 5;
if (true) {
let n = 10;
}
console.log(n); // 5
}
let
局域化的var,仅在块级作用域内有效,存在以下特性:
- 不存在变量名提升
- 暂时性死区:作用域内存在let,那么let声明的变量不会受外部影响。这么设计主要是为了避免使用在前,声明在后的不良习惯。 先声明后使用,扔掉那个所谓的变量名提升了吧..
var bb=2;
if(true){
console.log(aa);
console.log(bb); // ReferenceError: bb is not defined
var aa=1;
let bb;
}
- 不能重复声明一个变量:
var aa=1;
let aa=1; // "SyntaxError: Identifier 'aa' has already been declared
let aa=1; // 同上
const
声明常量,字面常量的话不改进行赋值修改;对象字面常量的话,可以修改其内部元素的值。
const aa=1;
aa=2; // TypeError: Assignment to constant variable.
const cc=[];
cc[0] =1;
cc[1] =2;
console.log(cc);
cc = [1,2,3]; // TypeError: Assignment to constant variable.
2. 解构赋值
如下面的例子:
let [x, , y] = [1, 2, 3]; // x:1 y:3
let [x = 1, y = x] = [2]; // x=2; y=2
var {x, y = 5} = {x: 1}; // x:1 y:5 设置默认值
var {x, y = 5} = {x: 1, y: undefined}; // x:1 y:5 undefined不影响默认值
var {x, y = 5} = {x: 1, y: null}; // x:1 y:null
var {a, b} = {b:1, a:1}; console.log(a); // a:1 b:1
const [a, b, c, d, e] = 'hello'; // a:'h' ... e:'o'
最基本的作用是交换变量的值: [x, y] = [y, x];
,可以由此进行衍生。
3. 字符串扩展
JavaScript允许采用\uxxxx形式表示一个字符,其中“xxxx”表示字符的码点。
Es6中提供了两个string和unicode互转函数:codePointAt ()和String.fromCharCode()
,相对于Es5中存在的两个函数:charCodeAt()和String.fromCharCode()
,功能有些区别:
var s = "𠮷";
s.length // 2
s.charAt(0) // ''
s.charAt(1) // ''
s.charCodeAt(0) // 55362
s.charCodeAt(1) // 57271
字符和unicode的互相转换方法:
var str2Unicode = function(str){
return "\\u" + ("00" + str.charCodeAt(0).toString(16)).slice(-4)
}
var unicode2Str = function(str){
return unescape(str);
}
以下是表示"z"的几种方法:
'\z' === 'z' // true
'\172' === 'z' // true
'\x7A' === 'z' // true
'\u007A' === 'z' // true
'\u{7A}' === 'z' // true Es6中引入
JavaScript内部,字符以UTF-16的格式储存,每个字符固定为2个字节。对于那些需要4个字节储存的字符(Unicode码点大于0xFFFF的字符),JavaScript会认为它们是两个字符。
Es6中引入了几个处理字符串的函数: includes(), startsWith(), endsWith() , repeat(), padStart(),padEnd()
。
Es6中引入的``
可以包含含有换行符的字符串,这样可以很方便的早console中处理字符串,这个也极大的方便了前端模板的处理。
前端模板示例:
var x = 1;
var y = 2;
console.log(`${x} + ${y} = ${x + y}`) // 1 + 2 = 3
4. 正则扩展
引入了u修饰符,用来正确处理大于\uFFFF
的Unicode字符。
/^\uD83D/u.test('\uD83D\uDC2A') // false
/^\uD83D/.test('\uD83D\uDC2A') // true
上面代码中,\uD83D\uDC2A
是一个四个字节的UTF-16编码,代表一个字符。但是,ES5不支持四个字节的UTF-16编码,会将其识别为两个字符,导致第二行代码结果为true。加了u修饰符以后,ES6就会识别其为一个字符,所以第一行代码结果为false。
var s = '𠮷';
/^.$/.test(s) // false
/^.$/u.test(s) // true
点(.)字符在正则表达式中,含义是除了换行符以外的任意单个字符。对于码点大于0xFFFF的Unicode字符,点字符不能识别,必须加上u修饰符。
5. 数字扩展
增加了几个数字处理函数:
Number.isFinite(),
Number.isNaN(),
Number.parseInt(),
Number.parseFloat(),
Number.isInteger(),
Number.EPSILON //极小值
Number.isSafeInteger() // -2^53到2^53之间
Math.trunc() // 去除一个数的小数部分,返回整数部分。
Math.sign() // 判断正负
Math.cbrt() // 求立方根
6. 数组扩展
提供了一下新的函数:
Arrary.from // [].slice类似
Array.of() // 转成数组
copyWithin(target, start = 0, end = this.length) // target(必需):从该位置开始替换数据。start(可选):从该位置开始读取数据,默认为0。如果为负值,表示倒数。end(可选):到该位置前停止读取数据,默认等于数组长度。如果为负值,表示倒数。
find()和findIndex() // 查找数据
fill() // 填充数组
includes() // 判断是否包含
7. 函数扩展
函数参数的默认值:
function foo(a, b=2){ console.log(a, b);}
函数作用域:
// 1. y()执行影响的是形参x,而且内部对x进行重新声明,因此对别的数值没什么影响。
var x = 1;
function foo(x, y = function() { x = 2; }) {
var x = 3;
y();
console.log(x);
}
foo(); // 3
console.log(x); // 1
// 2. y()只是影响了形参x
var x = 1;
function foo(x, y = function() { x = 2; }) {
x = 3;
y();
console.log(x);
}
foo(); // 2
console.log(x); // 1
// 3. 形参y管理的作用域是外部 因此会把外面的x的1改为2
var x = 1;
function foo(y = function() { x = 2; }) {
var x = 3;
y();
console.log(x);
}
foo(); // 3
console.log(x); // 2
扩展运算符...
将一个数组转为用逗号分隔的参数序列。如:
console.log(1, ...[2, 3, 4], 5) // 1 2 3 4 5
// 合并数组
[1, 2].concat(more) // ES5
[1, 2, ...more] // ES6
// 解构赋值
const [first, ...rest] = [1, 2, 3, 4, 5];
first // 1
rest // [2, 3, 4, 5]
// 字符串
[...'hello'] // [ "h", "e", "l", "l", "o" ]
// 实现了Iterator接口的对象
let map = new Map([
[1, 'one'],
[2, 'two'],
[3, 'three'],
]);
let arr = [...map.keys()]; // [1, 2, 3]
箭头函数本身没有this和arguments,只能引用外层的this:
function foo() {
return () => {
return () => {
return () => {
console.log('id:', this.id);
};
};
};
}
var f = foo.call({id: 1});
var t1 = f.call({id: 2})()(); // id: 1
var t2 = f().call({id: 3})(); // id: 1
var t3 = f()().call({id: 4}); // id: 1
// arguments
function foo() {
setTimeout(() => {
console.log('args:', arguments);
}, 100);
}
foo(2, 4, 6, 8)
// args: [2, 4, 6, 8]
由于箭头函数没有自己的this,所以当然也就不能用call()、apply()、bind()这些方法去改变this的指向
(function() {
return [
(() => this.x).bind({ x: 'inner' })()
];
}).call({ x: 'outer' }); // ['outer']
8. 对象扩展
引入了一下几个函数:
Object.is() // 判断两个值是否相等 和===类似
// 区别
+0 === -0 //true
NaN === NaN // false
Object.is(+0, -0) // false
Object.is(NaN, NaN) // true
Object.assign() // 合并对象
// 潜copy
var obj1 = {a: {b: 1}};
var obj2 = Object.assign({}, obj1);
obj1.a.b = 2;
obj2.a.b // 2
// 属性是替换 而不是覆盖
var target = { a: { b: 'c', d: 'e' } }
var source = { a: { b: 'hello' } }
Object.assign(target, source) // { a: { b: 'hello' } }
Object.getOwnPropertyDescriptor // 属性的描述对象
// for...in循环、Object.keys()、JSON.stringify()、Object.assign()均会忽略enumerable为false的属性
Object.keys()、Object.values() 、Object.entries() // 获取key、value和键值对
9. Symbol
Undefined、Null、布尔值(Boolean)、字符串(String)、数值(Number)、对象(Object)之外的第七种类型。凡是属性名属于Symbol类型,就都是独一无二的,可以保证不会与其他属性名产生冲突。
// 可以显示转换成别的类型
var sym = Symbol('My symbol');String(sym) // 'Symbol(My symbol)'
sym.toString() // 'Symbol(My symbol)'
// Symbol值不能与其他类型的值进行运算,会报错。
var sym = Symbol('My symbol');
"your symbol is " + symbol // TypeError
Symbol作为属性名,该属性不会出现在for...in、for...of循环中,也不会被Object.keys()、Object.getOwnPropertyNames()返回。可通过Object.getOwnPropertySymbols返回。
10. Proxy和Reflect
Proxy可以理解成,在目标对象之前架设一层“拦截”,外界对该对象的访问,都必须先通过这层拦截,因此提供了一种机制,可以对外界的访问进行过滤和改写。Proxy这个词的原意是代理,用在这里表示由它来“代理”某些操作,可以译为“代理器”。
var obj = new Proxy({}, {
get: function (target, key, receiver) {
console.log(`getting ${key}!`);
return Reflect.get(target, key, receiver);
},
set: function (target, key, value, receiver) {
console.log(`setting ${key}!`);
return Reflect.set(target, key, value, receiver);
}
});
obj.count = 1 // setting count!
++obj.count // getting count! setting count! 2
Reflect:将Object对象的一些明显属于语言内部的方法(比如Object.defineProperty),放到Reflect对象上;或者修改某些Object方法的返回结果,让其变得更合理。
11. Set和Map
- Set:类似于数组,但是没有重复的值
var set = new Set([1, 2, 3, 4, 4]); [...set] // 1 2 3 4
属性: size
操作方法: add、delete、has、clear
遍历方法:keys()、values()、entries()、forEach()
- Map:类似于对象,是键值对的集合,但是键值不限于字符串
var m = new Map();
var o = {p: "Hello World"};
m.set(o, "content")
m.get(o) // "content"
属性、操作方法和遍历方法与Set类似
12. Class
Class和function相似:
// function
function Point(x, y) {
this.x = x;
this.y = y;
}
Point.prototype.toString = function () { ... };
// class
class Point {
constructor(x, y) {
this.x = x;
this.y = y;
}
toString() { ... }
}
区别:
- Class中的方法是不可枚举的(enumerable:false),而function就是可以的。
借用Symbol实现私有方法:
class foo({
// 共有方法
foo (baz) {
this[bar](baz);
}
// 私有方法
[bar](baz) {
return this[snaf] = baz;
}
});
静态方法:
class Foo {
static classMethod() {
return 'hello';
}
}
Foo.classMethod()
静态属性:
// 1.2 两种写法都无效(Es6)
class Foo {
// 1
prop: 2
// 2
static prop: 2
}
// 有效
Foo.prop = 1;
new.target: 非new操作时为undefined,否则为类构造函数
function Person(name) {
if (new.target !== undefined) {
this.name = name;
} else {
throw new Error('必须使用new生成实例');
}
}
网友评论