目录
let和const命令
模板字符串
扩展运算符
解构赋值
对象解构
数组解构
扩展的函数
带参数默认值的函数
剩余参数表示不定参
箭头函数
扩展的对象
直接写入变量和函数,作为对象的属性和方法
新增Object.is()/Object.assign()/Object.keys/Object.value/Object.entries/Object.getOwnPropertyDescriptors方法
扩展的数值
Symbol
Map和Set
Set
Map
迭代器和生成器/Proxy对象
Promise
类class
模块化实现
es6新增了两个声明变量的关键字:let和const;
console.log(a); // undefined 变量提升了 实际代码变为 var a; console.log(a)console.log(b); // 报错 Uncaught ReferenceError: Cannot access 'b' before initializationconsole.log(c); // 报错 Uncaught ReferenceError: Cannot access 'c' before initializationvar a = 120;let b = 'false';const c = 100;
// 使用var
var arr = [];for (var i = 0; i < 10; i++) {arr[i] = function() {return i};}
console.log(arr[5]()); // 10// 使用let或const
const arr = [];for (let i = 0; i < 10; i++) {arr[i] = function() {return i};}
console.log(arr[5]()); // 5
if(true) {var a = 120;let b = 'false';const c = 100;
}
console.log(a); // 120
console.log(b); // 报错:Uncaught ReferenceError: b is not defined
console.log(c); // 报错:Uncaught ReferenceError: c is not defined
var a = 120;
let b = 'false';
const c = 100;
var a = 130;
let b = 'true'; // Uncaught SyntaxError: Identifier 'b' has already been declared
const c = 200; // Uncaught SyntaxError: Identifier 'c' has already been declared
console.log(a); // 130
const b = false;
b = 12;
console.log(b); // Uncaught TypeError: Assignment to constant variable
console.log(window.RegExp); // ƒ RegExp() { [native code] }
let RegExp = 10;
console.log(RegExp); // 10
console.log(window.RegExp); // ƒ RegExp() { [native code] }
使用反引号``来创建模板字符串,插入变量时使用${变量名};
let name = '小明';let age = '12';console.log(name + '今年'+ age + '岁啦!'); // 小明今年12岁啦!console.log(`${name}今年${age}岁啦!`); // 小明今年12岁啦!
使用该方法可避免了大量+ 和 ' '的配合使用;
扩展运算符是指...,用于扩展可迭代类型或数组;
const arry1 = ['小明', '小红'];
const arry2 = [...arry1, '小李', '小强'];
console.log(arry2); // ['小明', '小红', '小李', '小强']
const arry1 = ['小明', '小红'];
const arry2 = [...arry1];
console.log(arry2); // ['小明', '小红']
arry2[2] = '小强';
console.log(arry1, arry2); // ['小明', '小红'] ['小明', '小红', '小强']
使用扩展运算符拷贝的结果不是简单拷贝的引用地址,因此改变不会受影响;
const obj1 = {name: '小明', age: 12};
const obj2 = {hobby: '踢足球'};
const obj3 = {...obj1, ...obj2}
console.log(obj3); // {name: '小明', age: 12, hobby: '踢足球'}
对象扩展运算符,层数是1的话为深拷贝。二级以上的层级则不是深拷贝;
const obj1 = {name: '小明', age: 12};
const obj2 = {project: {English: 20,huaxue: 30,}
};
const obj3 = {...obj1, ...obj2}
console.log(obj3); // {name: '小明', age: 12, hobby: '踢足球'}
obj3.project.huaxue = 90
console.log(obj2); // project: {English: 20, huaxue: 90} obj2的huaxue属性也被改变了
console.log(obj3); // {name: '小明', age: 12, project: {English: 20, huaxue: 90}
解构赋值是对赋值运算符的一种扩展,它是一种针对数组或对象进行模式匹配,然后对其中的变量进行赋值,可使代码简洁易读;
let student = {name: '小凡',age: 18}let {name, age} = studentconsole.log(name, age); // 小凡 18
对象解构时左侧变量名要与对象中key值对应,用{}
let student = {name: '小凡',age: 18
}
let {name, age, sex} = student
console.log(name, age, sex); // 小凡 18 undefined
也可以进行非完全解构;
let student = {name: '小凡',age: 18,sex: '男'
}
let {name} = student
console.log(name); // 小凡
可与扩展运算符搭配使用;
let student = {name: '小凡',age: 18,sex: '男'
}
let {name, ...attribute} = student
console.log(name, attribute); // 小凡 {age: 18, sex: '男'}
所有的变量都放到扩展变量中;
let student = {name: '小凡',age: 18,sex: '男',school: {name: '一中',location: '村里'}}let {name, school, ...attribute} = studentconsole.log(name,school, attribute); // 小凡 {name: '一中', location: '村里'} {age: 18, sex: '男'}
数组解构使用[ ],左侧变量名任意;
let student = ['小凡', 18, '男'];
[name, age, sex] = student
console.log(name, age, sex); // 小凡 18 男
其它与对象解构一样;
ES6添加了参数默认值,所以不用在函数内部编写容错代码;
// es5的写法
function add(a,b) {a = a || 10; // 若无定义a,则默认为10b = b || 20; // 若无定义b,则默认为20return a+b
}
console.log(add()); // 30// es6的写法
function add(a = 10, b = 20) {return a + b
}
console.log(add()); // 30
不定参功能和es5的arguments一样;
// es5写法
function pick(obj) {let result = {};for(let i = 1; i < arguments.length; i++) {result[arguments[i]] = obj[arguments[i]]}return result;
}
let book = {name: '活着',author: '余华',pages: 400
}
let bookData = pick(book, 'name', 'author','pages');
console.log(bookData); // {"name": "活着", "author": "余华","pages": 400}
function pick(obj, ...keys) {let result = {};for(let i = 0; i < keys.length; i++) {result[keys[i]] = obj[keys[i]];}return result;
}
let book = {name: '活着',author: '余华',pages: 400
}
let bookData = pick(book, 'name', 'author','pages');
console.log(bookData); // {"name": "活着", "author": "余华","pages": 400}
在箭头函数中没有arguments,也没有prototype属性,箭头函数不是一个对象,所以不能用new关键字来实例化箭头函数;
它使用=>来定义,function() {} 等价于 () => {}
箭头函数的this指向用于指向其父级对象的this
// es6写法
const name = "活着";
const author = "余华";const book = {name,author,sayName() {console.log('这是一本很好看的书籍');}
}
book.sayName() // 这是一本很好看的书
上面简写方式name,只能在属性和属性值相同的情况下简写~
// es5写法
const name = "活着";
const author = "余华";const book = {name: name,author: author,sayName: function() {console.log('这是一本很好看的书籍');}
}
book.sayName() // 这是一本很好看的书
Object.is()方法用来判断两个值是否严格相等,返回布尔值;与===区别在于对于NaN和+0、-0的处理结果不一样;
object1 = {name: '小明',age: 12
}
object2 = {name: '小明',age: 12
}
console.log(object2.name === object2.name); // true
console.log(Object.is(object1.name, object2.name)); // true
console.log(null === null); // true
console.log(Object.is(null, null)); // true
console.log(NaN === NaN); // false
console.log(Object.is(NaN, NaN)); // true
console.log(Object.is(+0,-0)); // false
console.log(+0 === -0); // true
// 补充几个烦人的比较
console.log(null instanceof Object); // false,但null也是个对象
console.log(null === undefined); // false
console.log(null == undefined); // true
console.log(NaN == NaN); // false
console.log(undefined == undefined); // true
var x = new Boolean(false);
console.log(x); // Boolean {false}
var y = Boolean(0);
console.log(y); // false
Object.assign()方法用于合并多个对象中的所有可枚举属性,并返回目标对象;是个浅拷贝方法~
object1 = {name: '小明',age: 12
}
object2 = {sex: 'male'
}
console.log(Object.assign(object1, object2)); // {name: '小明', age: 12, sex: 'male'}
Object.keys()
Object.keys()用于返回对象中的所有属性,返回一个数组
object1 = {name: '小明',age: 12
}
console.log(Object.keys(object1)); // ['name', 'age']
Object.values()用于返回对象中所有属性值,返回一个数组
object1 = {name: '小明',age: 12
}
console.log(Object.values(object1)); // [['小明', 12]
Object.entries()用于返回多个数组,每个数组都由key-value组成
object1 = {name: '小明',age: 12,classes: ['语文', '数学', '英语']}console.log(Object.entries(object1)); // [ "name","小明"],["age",12],["classes",["语文","数学","英语"] ] ]
该方法返回指定对象所有自身属性的描述对象;
通过字面量创建出来的对象,默认可枚举属性enumerable为true,可配置属性configurable(是否可删除等属性)为true,writable属性为true;
补充:通过Object.creat()方法创建一个对象,使用现有的对象来作为新创建对象的原型prototype。
console.log(0.1+0.2 === 0.3); // false
// 但是可以写个函数 判断如果0.1+0.2 与0.3相差小于Number.EPSILON,则表明0.1+0.2 与0.3相等
console.log(Number.isFinite(100)); // true
console.log(Number.isFinite(100/0)); // false
console.log(Number.isFinite(Infinity)); // false
console.log(Number.isNaN(NaN)); // true
console.log(Number.isNaN(0)); // false
console.log(Number.parseInt('321flos3')); // 321
console.log(Number.parseInt('3.21flos3')); // 3
console.log(Number.parseFloat('3.21flos3')); // 3.21
console.log(Number.parseFloat('3.2.1flos3')); // 3.2
console.log(Number.isInteger(3.21)); // false
console.log(Number.isInteger('3')); // false
console.log(Number.isInteger(3)); // true
console.log(Math.trunc(3.45)); // 3
console.log(Math.sign(3.45)); // 1
console.log(Math.sign(-3.45)); // -1
console.log(Math.sign(0)); // 0
新增一种基本数据类型symbol,表示独一无二的值。特点如下:
symbol的值是唯一的,用来解决命名冲突的问题;
Symbol值不能与其他数据进行运算;
通过Symbol()或Symbol.for()创建Symbol值;
Symbol定义的对象属性不能使用for...in循环遍历,但是可以使用Reflect.ownKeys来获取对象的所有键名;
一般在创建对象的某个属性唯一时,使用Symbol
Symbol是JavaScript中的第六种基本数据类型,与undefined、null、Number、String、Boolean并列~
ES6提供了新的数据结构Set(集合),但成员的值都是唯一的,集合实现了iterator接口,所以可以使用扩展运算符和for...of...进行遍历;
Set对象的属性和方法主要有:
size: 返回集合的元素个数(相当于数组中的length属性);
add:增加一个新元素,返回当前集合;
delete:删除元素,返回布尔值;
has:检测集合中是否包含某个元素,返回布尔值;
let newSet = new Set([1,3]);console.log(newSet); // Set(2) {1, 3}console.log(newSet.add([4,5])) // Set(3) {1, 3, [4, 5]}console.log(newSet.delete(3)) // trueconsole.log(newSet.delete(4)) // falseconsole.log(newSet.has(1)) // trueconsole.log(newSet.size); // 2
let newSet = [...new Set([1,3,3,5,4,4,6,7])];console.log(newSet); // [1, 3, 5, 4, 6, 7]
let arr1 = [1,2,3,4,5];
let arr2 = [1,4,6,7];
let arr3 = [...new Set(arr1)].filter(item => new Set(arr2).has(item))
console.log(arr3); // [1, 4]
let arr1 = [1,2,3,4,5];
let arr2 = [1,4,6,7];
let arr3 = [...new Set(arr1)].filter(item => !(new Set(arr2).has(item)))
console.log(arr3); // [2,3,5]
let arr1 = [1,2,3,4,5];let arr2 = [1,4,6,7];let arr3 = [...new Set([...arr1, ...arr2])]console.log(arr3); // [1, 2, 3, 4, 5, 6, 7]
ES6提供了Map数据结构,是键值对的集合,键的定义不再像对象一样仅局限于字符串,而是包含各种类型的值(包括对象)。同时,因为Map实现了iterator接口,所以可以使用for...of进行遍历;
Map的属性和方法主要有:
size: 返回Map的元素个数
set:增加一个新元素,返回当前Map;
get:返回键值对象的键值;
has:检测当前Map中是否包含某个元素,返回布尔值;
clear:清空集合,返回undefined
let newMap = new Map();
newMap.set('name', '小明');
newMap.set('classes', ['语文', '数学', '英语']);
console.log(newMap); // Map(2) {'name' => '小明', 'classes' => Array(3)}
console.log(newMap.size); // 2
console.log(newMap.has('name')); // true
for (const item of newMap) {console.log(item); // (2) ['name', '小明'] (2) ['classes', Array(3)]
}
console.log(newMap.delete('classes')); // true
console.log(newMap.size); // 1
console.log(newMap.get('name')); // 小明
回头详细讲
见2023年了,你还在为Promise头疼?_迷糊的小小淘的博客-CSDN博客
类的本质依然是一个函数
见JavaScript高级教程(面向对象编程)_迷糊的小小淘的博客-CSDN博客
模块化是为了将复杂的程序按照一定的规则拆分成单个文件,并最终组合在一起,可以降低代码复杂度,避免命名冲突,提高复用性;
ES6中的模块化功能主要由两个命令构成:export和import,export命令用于暴露模块的对外接口,import命令用于引入其它模块提供的功能;
导出模块有三种不同的暴露方式:
如果导出模块采用分别暴露的方式,如:
// test.js文件// 通用暴露
export let name = '小明';
export function exam() {console.log('明天又要考试~');
}
如果导出模块采用统一暴露的方式,如:
// test.js文件
// 统一暴露
let name = '小明';
function exam() {console.log('明天又要考试~');
};
export {name, exam};
注意此处{name, exam}并不是表示解构赋值,只是表示一种写法~
则导入模块时要使用:
如果导出模块采用默认暴露的方式,该种方式一般应用于一个文件中只有一个暴露,如:
// test.js文件
// 默认暴露
export default {name : '小明',exam: function() {console.log('明天又要考试~');}
};
根据暴露模块的方法不同,引入模块也有不同的导入方式:
上述三种暴露方式都可使用该种方法:
对于前两种暴露方式,可直接通过下述代码拿到name或exam
但是对于默认暴露来说,要采用如下:
以上三种暴露方式可同时在另一个文件中引入,不会产生覆盖
此处,简单补充下另一个重要的模块化规范方式CommonJs:
CommonJs方式模块化的代码既可在服务器端,如nodejs中运行,又可以在浏览器端运行(需借助工具Browserify编译),他仅有两种暴露方式:
原理是在服务端exports===module.exports={ },它俩都指向同一个空对象;
这两种方式不能混用,如果混用,则以module.exports暴露的为主,value是啥,module.exports暴露的就是啥;
显示并没有englishName这一属性,
引入方式也仅有两种,
下一篇:Django框架之模型系列