ES6之扩展
模板字符串
反引号``
1,在反引号中使用${}可以插入js中的变量以及函数。
2,反引号中可以嵌套反引号。
3,不需要顾及普通单引号和双引号所带来的字符串拼接以及转义的问题。
// 模版字符串 // 'asdffdsa' // "asdfasdf" // `asdfasdffsa` // const xiaoming = { // name: 'xiaoming', // age: 14, // say1: function() { // console.log('我叫' + this.name.toUpperCase() + ', 我今年' + this.age + '岁!'); // }, // say2: function() { // console.log(`我叫${ `Mr.${ this.name.toUpperCase() }` }, 我今年${ this.age }岁!`); // } // } // xiaoming.say1(); // xiaoming.say2(); const getImoocCourseList = function() { // ajax return { status: true, msg: '获取成功', data: [{ id: 1, title: 'Vue 入门', date: 'xxxx-01-09' }, { id: 2, title: 'ES6 入门', date: 'xxxx-01-10' }, { id: 3, title: 'React入门', date: 'xxxx-01-11' }] } }; const { data: listData, status, msg } = getImoocCourseList(); function foo(val) { return val.replace('xxxx', 'xoxo'); } if (status) { let arr = []; listData.forEach(function({ date, title }) { // arr.push( // '<li>\ // <span>' + title + '</span>' + // '<span>' + date + '</span>' + // '</li>' // ); arr.push( ` <li> <span>${ `课程名: ${ title }` }</span> <span>${ foo(date) }</span> </li> ` ); }); let ul = document.createElement('ul'); ul.innerHTML = arr.join(''); document.body.appendChild(ul); } else { alert(msg); }
模板字符串的部分新方法
// 部分新方法 // padStart padEnd 字符串的补全或是填充。 { let str = 'i'; let str1 = str.padStart(5, 'mooc');//第一个参数代表将字符串填充到5位。若是6为则输出moocmi console.log(str1);//输出为mooci let str2 = str.padEnd(5, 'mooc');//与上方不同的地方在于在末尾补充 console.log(str2); } // repeat 字符串的重复 { 'i'.repeat(10);//打印出10个i,这里的参数只能为大于-1的数,若不是整数会自动取整。
//自己实现的repeat()方法 function repeat(str, num) { return new Array(num + 1).join(str);//这里的Array()构造函数的参数为一个数字的时候,代表数组元素的个数。 } console.log(repeat('s', 3)); } // startsWith endsWith 判断字符串是否为(参数)开头或结尾。 { const str = 'A promise is a promsie'; console.log(str.startsWith('B')); console.log(str.startsWith('A pro')); console.log(str.endsWith('promsie')); console.log(str.endsWith('A')); } // includes 判断字符串中是否存在(参数)。 { const str = 'A promise is a promise'; // if (str.indexOf('promise') !== -1) { if (~str.indexOf('promise')) {//这里的~表示按位取反 console.log('存在1'); } if (str.includes('a promise')) { console.log('存在2'); } }
补充:
padStart()用于头部补全,即:把ab补全到xxx的头部,如果用来补全的字符串与原字符串,两者的长度之和超过了指定的最小长度,则会截去超出位数的补全字符串。
repeat方法返回一个新字符串,表示将原字符串重复n次,参数如果是小数,会被取整。
for-of遍历字符串以及unicode表示法
let str = 'PROMISE'; /***************************************************************/ // ES6之前遍历字符串的方式 // 使用for循环 // for (var i = 0, len = str.length; i < len; i ++) { // console.log(str[i]);//用数组的方式取字符串中的子串 // console.log(str.charAt(i));//用字符串的charAt()方法。参数为下标。 // } /***************************************************************/ // 转成数组后遍历 // var oStr = Array.prototype.slice.call(str); var oStr = str.split(''); // const oStr = [...str]; // const [...oStr] = str; // oStr.forEach(function(word) { // console.log(word); // }); // console.log(oStr); // 有时候遍历是为了操作字符串 // 对全是英文的字符串中的大写字符加密 A -> 100 B -> 99。。。 const map = {A: '100', B: '99', C: '98', D: '97', E: '96', F: '95', G: '94', H: '93', I: '92', J: '91', K: '90', L: '89', M: '88', N: '87', O: '86', P: '85', Q: '84', R: '83', S: '82', T: '81', U: '80', V: '79',W: '78',X: '77',Y: '76', Z: '75'}; const words = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'; oStr.forEach(function(word, index) { if (words.includes(word)) oStr[index] = map[word]; }); console.log(oStr.join('')); /***************************************************************/ // 使用for-of遍历字符串//类似for-in // for (let word of str) { // console.log(word); // } let newStr = ''; for (let word of str) { if (words.includes(word)) newStr += map[word]; } console.log(newStr) /***************************************************************/ // 🐶 \u1f436 unicode码(点)。emoji console.log('\u1f436'); console.log('\u{1f436}'); // Unicode是一项标准 包括字符集、编码方案等 // 他是为了解决传统的字符编码方案的局限而产生的,为每种语言中的每个字符设定了统一并且唯一的二进制编码,以满足跨语言、跨平台进行文本转换、处理的要求。 // codePointAt 获取字符串中对应字符的一个码点 // '🐶'.codePointAt(0);//这样出来的是10进制的数字,还需要经过toString(16)的转换,转换为16进制。 // at 根据下标取字符//浏览器的支持不是很好,可通过工具编译ES6的代码编译成ES5的代码,这样就可以执行了。 // '🐶abc'.at(0) 🐶
一般情况下,在解析字符串的时候碰到\u的时候,只会把后四位unicode码点解析成对应的字符。
ES6提供了一种方式\u{1f436}添加上大括号就可以解析四位以上的码点。
正则扩展(u, y修饰符)
const regexp1 = /^a/g; const regexp2 = new RegExp('^a', 'g'); const regexp3 = new RegExp(/a/g); const regexp4 = new RegExp(/a/); console.log('aabbcc'.match(regexp1)); console.log('babbcc'.match(regexp1)); console.log('aabbccaabbaa'.match(regexp3)); console.log('aabbccaabbaa'.match(regexp4)); // 构造函数的变化,在ES6中的变化,第二个(修饰符)参数会覆盖前面的修饰符。 const regexp5 = new RegExp(/a/giuy, 'ig');//在ES5中会报错
一般情况是用字面量的形式比较多,用到构造函数的方式时,一般是在动态生成正则的情况。
// uy修饰符 // u. unicode 通过u修饰符识别大于两个字节的unicode字符。 console.log(/^\ud83d/.test('\ud83d\udc36'))//这个情况下会返回true,js将字符串识别成了两个unicode字符。第一个字符被匹配到了。 console.log(/^\ud83d/u.test('\ud83d\udc36'))//这里加了u修饰符,会将整个字符串的4个字节当作一个unicode 的字符来处理。 // '\ud83d\udc36'这个整个其实是小狗的表情🐶 // y 粘连修饰符 sticky 需要保证从上一个匹配结果的索引开始就满足匹配条件,这样才会进行下一次匹配。 const r1 = /imooc/g; const r2 = /imooc/y; const str = 'imoocimooc-imooc'; console.log(r1.exec(str)); console.log(r1.exec(str)); console.log(r1.exec(str)); console.log(r1.exec(str)); console.log('-----------------'); console.log(r2.exec(str)); console.log(r2.exec(str)); console.log(r2.exec(str));//意思就是没有连在一起的相同的字符串就匹配不到。
^匹配输入字行首,如果设置了RegExp对象的Multiline属性,^也匹配“\n”或“\r”之后的位置。
.点(.)字符在正则表达式中,含义是除了换行符以外的任意单个字符。对于码点大于0xFFFF的 Unicode 字符,点字符不能识别,必须加上u修饰符。
$匹配输入行尾。如果设置了RegExp对象的Multiline属性,$也匹配“\n”或“\r”之前的位置。
Test()如果字符串 string 中含有与 RegExpObject 匹配的文本,则返回 true,否则返回 false。
数值扩展
ES6在Number对象上新提供的一些方法:
// 新的进制表示法 //在不兼容es6的浏览器中,可以使用Number()转换为10进制数。
//es6中,会自动转换为10进制 // 016 => 14 //js中旧的八进制 // 0o 0O octonary //ES6中新的八进制 // 0b 0B binary // console.log(0o16); // console.log(0b1111);
// 新的方法与安全数 // --------------------------------------------------- // Number.parseInt Number.parseFloat //ES6中将window上的parseInt()挂载到了Number对象上,效果相同。 // console.log(window.parseInt('1.23')); // console.log(parseFloat('1.23')); // console.log(Number.parseInt(1.23)); // console.log(Number.parseFloat(1.23)); // --------------------------------------------------- // Number.isNaN Number.isFinite //这是Number对象上的新增方法 // isNaN 不同于window.isNaN(),这里是判断是否为NaN,若是NaN则返回true。
// console.log(Number.isNaN(NaN)); // console.log(Number.isNaN(-NaN)); // console.log(Number.isNaN(1)); // console.log(Number.isNaN('1')); // console.log(Number.isNaN(true)); // function isNaN(value) { // return value !== value; // } // console.log(isNaN(NaN)); // console.log(isNaN(-NaN)); // console.log(isNaN(1)); // console.log(isNaN('1')); // console.log(isNaN(true)); // isFinite //判断是否为有意义(有限)的数字,如果是数字则返回true,否则返回false // console.log(Number.isFinite(Infinity)); // console.log(Number.isFinite(2 / 0)); // console.log(Number.isFinite(2 / 4)); // console.log(Number.isFinite(1234)); // console.log(Number.isFinite('1234')); // console.log(Number.isFinite(true)); // console.log(Number.isFinite(NaN)); // --------------------------------------------------- // Number.MAX_SAFE_INTEGER Number.MIN_SAFE_INTEGER // Number.isSafeInteger(); //安全数,判断整数,负的2的53次方-1~正的2的52次方-1 // console.log(Number.MAX_SAFE_INTEGER); //值为正的2^53-1 // console.log(Number.MIN_SAFE_INTEGER); //值为负的2^53-1
// console.log(Number.isSafeInteger(Number.MAX_SAFE_INTEGER - 1));
// console.log(Number.isSafeInteger(Number.MAX_SAFE_INTEGER + 1));
// ---------------------------------------------------
// 幂运算 ** //默认从右往左计算,右结合,需要加括号才会按正常思路。
// let a = (2 ** 10) ** 0;
// console.log(a);
// Math //es6也增加了一些关于这个对象的方法,自行搜索。
函数扩展
// 函数参数的默认值//参数默认值在es5中的处理:
//function add( a, b ) {
// b = b || 999;//或者进行if操作。
// console.log(a,b)
//}
//es6的做法: // function add(a, b = 999 + b, c = 1) { //在进行参数的计算的时候,不能出现在此之后定义的变量 // console.log(a, b); // } // add(1); function People({ name, age = 38 } = {name: 1}) { console.log(name, age); }; People({ name: 3 });
补充:使用参数默认值时,函数不能有同名参数,否则就报错。
// 结合扩展运算符(剩余参数...只能是最后一个参数使用,用于聚合)扩展运算符用于展开
//es5利用arguments类数组对象。
// function sum(...args) {//将类数组对象转化为数组的3种方式。 // // let args = Array.prototype.slice.call(arguments); // // let args = [...arguments]; // // let [...args] = arguments; // console.log(args); // } // sum(1, 2, 321, 4354, 'fdafsd'); // function op(type, b, ...nums) { // console.log(type); // console.log(nums); // } // op('sum', 1, 23, 454, 3, 67, 234); function sum(...numbers) { return numbers.reduce(function(a, b) {//遍历,第一次a=0,b=1,第二次a=return的值,b为2(也就是下面调用的参数),以此类推。 return a + b; }, 0); } console.log(sum(1, 2, 3, 4));
// 箭头函数 // const add1 = (a, b) => { // a += 1; // return a + b; // }; // const add2 = function(a, b) { // a += 1; // return a + b; // } // console.log(add1(2, 2)); // console.log(add2(2, 2)); // const pop = arr => void arr.pop(); //箭头函数只有一个参数可以不加括号。
//默认情况下,一行的箭头函数会返回值,这里加上void关键字,设置没有返回为undefined。 // console.log(pop([1, 2, 3])); // const log = () => {//箭头函数中没有arguments对象,所以只能用...剩余参数。来获取参数。 // console.log(arguments); // }; // log(1, 2, 3); // const xiaoming = { // name: '小明', // say1: function() { // console.log(this); // }, // say2: () => {
//箭头函数没有自己的this,将会取到当前所处环境下所指的this,
//这里箭头函数say2处在xiaoming对象环境内,取到的是小明的this,即window,这里将会打印window。 // console.log(this); // } // } // xiaoming.say1(); // xiaoming.say2(); // const xiaoming = { // name: 'xiaoming', // age: null, // getAge: function() { // let _this = this; // // ...ajax // setTimeout(function() { // _this.age = 14; // console.log(_this); // }, 1000); // } // }; // xiaoming.getAge(); const xiaoming = { name: 'xiaoming', age: null, getAge: function() { // ...ajax setTimeout(() => { this.age = 14; console.log(this);这里的箭头函数处在getage函数内,它的this是xiaoming,所以this为xiaoming对象
}, 1000); } }; xiaoming.getAge();
对象扩展
// 简洁表示法 // const getUserInfo = (id = 1) => { // // AJAX .... // const name = 'xiaoming'; // const age = 10; // return { // name: name, // age: age, // say: function() { // console.log(this.name + this.age); // } // }; // }; // const xiaoming = getUserInfo(); // ------------------------------------------ // const getUserInfo = (id = 1) => { // // AJAX .... // const name = 'xiaoming'; // const age = 10; // return { // name,//es6中,这里会自动找同名属性,并得到它的属性值。 // age, // say() {//方法可以直接使用方法名加括号的形式。 // console.log(this.name + this.age); // } // }; // }; // const xiaoming = getUserInfo(); // ------------------------------------------ // 属性名表达式 // const obj = { // a: 1, // $abc: 2, // 'FDASFHGFgfdsgsd$#$%^&*%$#': 3 // }; const key = 'age'; const xiaoming = { name: 'xiaoming', [`${key}123`]: 14//属性名表达式,支持字符串的拼接。 };
注意:属性名表达式与简洁表示法,不能同时使用,会报错。
// 扩展运算符 // 复制对象 - 浅拷贝//改变原对象或者拷贝完的对象,另一个会被影响。 // const obj1 = { // a: 1, // b: 2, // d: { // aa: 1, // bb: 2 // } // }; // const obj2 = { // c: 3, // a: 9 // }; // const cObj1 = { ...obj1 }; // console.log(cObj1.d.aa); // cObj1.d.aa = 999; // console.log(cObj1.d.aa); // console.log(obj1.d.aa); // 合并对象-浅拷贝 // const newObj = { // ...obj2, // ...obj1//出现重复的属性,后面插入的相同的属性的值将会代替前面相同属性的值, // }; // newObj.d.aa = 22; // console.log(obj1); // ----------------------------------- // 部分新的方法和属性 // Object.is//Object.is()该方法传入两个参数,比较参数1===参数2 // === // +0 -0//唯一与===两个不同的差别。 // NaN//唯一与===两个不同的差别。 // console.log(Object.is(+0, -0));//false // console.log(+0 === -0);//true // console.log(Object.is(NaN, NaN));//true // console.log(NaN === NaN);//false // console.log(Object.is(true, false)); // console.log(Object.is(true, true)); // -------------------------------------------------- // Object.assign
//Object.assign()-浅拷贝。赋值或者合并一个对象时常用,第一个参数为将返回的对象,后面的所有参数,将会与第一个合并。 // const obj = Object.assign({a: 1}, {b: 2}, {c: 3}, {d: 4, e: 5}); // const obj = { // a: 1, // b: { // c: 2 // } // }; // let newObj = Object.assign({a: 3}, obj); // console.log(newObj.b.c); // newObj.b.c = 100; // console.log(obj.b.c); // -------------------------------------------------- // const obj = { // a: 1, // b: 2, // c: 3, // d: 4 // }; // Object.keys // console.log(Object.keys(obj));//返回自身所有可枚举属性的数组 // // Object.values // console.log(Object.values(obj));//返回自身所有可枚举属性的值的数组 // // Object.entries // console.log(Object.entries(obj));//返回自身所有可枚举属性和值的数组的数组 // for - of//可结合以上三种方法遍历对象。 // for (let [k, v] of Object.entries(obj)) { // console.log(k, v); // } // -------------------------------------------------- // __proto__//建议实际编码尽量别用,调试用用就好。 // console.log({a: 1}); // -------------------------------------------------- // Object.setPrototypeOf//修改对象的原型__proto__,性能不太好,个人建议尽量别使用 // const obj1 = { // a: 1 // }; // const obj2 = { // b: 1 // } // const obj = Object.create(obj1); // console.log(obj.__proto__); // Object.setPrototypeOf(obj, obj2); // console.log(obj.__proto__); // -------------------------------------------------- // Object.getPrototypeOf//获取对象的原型 // const obj1 = {a: 1}; // const obj = Object.create(obj1); // console.log(obj.__proto__); // console.log(Object.getPrototypeOf(obj)); // console.log(obj.__proto__ === Object.getPrototypeOf(obj));//true // -------------------------------------------------- // super//可以访问到对象的原型对象 const obj = {name: 'xiaoming'}; const cObj = { say() {//只有在对象的简洁表示法中,才可以使用super关键字,否则会报错,使用箭头函数也不行。 console.log(`My name is ${super.name}`); } } Object.setPrototypeOf(cObj, obj); cObj.say();
注意: 解构赋值不会拷贝继承自原型对象的属性。
Object.entries方法返回一个数组,成员是参数对象自身的(不含继承的)所有可遍历(enumerable)属性的键值对数组。
Object.values方法返回一个数组,成员是参数对象自身的(不含继承的)所有可遍历(enumerable)属性的键值。
Object.keys方法,返回一个数组,成员是参数对象自身的(不含继承的)所有可遍历(enumerable)属性的键名。
super关键字,指向的是当前对象(this指向的对象)的原型对象。
数组扩展
// 结合扩展运算符使用 // function foo(a, b, c) { // console.log(a); // console.log(b); // console.log(c); // } // foo(...[1, 3, 2]);//用处,数据交互使用数组更节省流量,从后端接收数据。 // const user = ['小明', 14, ['吃饭', '打游戏'], '我没有女朋友']; // function say(name, age, hobby, desc) { // console.log(`我叫${ name }, 我今年${ age } 岁, 我喜欢${ hobby.join('和') }, ${ desc }`); // } // say(user[0], user[1], user[2], user[3]); // say(...user); // apply // say.apply(null, user); // const arr = [1, 2, 233, 3, 4, 5]; // // Math.max(); // console.log(Math.max(...arr)); // console.log(Math.max.apply(null, arr)); // console.log(Math.min(...arr)); // console.log(Math.min.apply(null, arr)); // --------------------------------------------
//数组的合并 // const arr1 = [1, 2, 3, 4]; // const arr2 = [4, 2, 2, 1]; // const arr3 = [2.2, '123', false]; // const cArr1 = [1, 2, 3, ...arr3]; // const cArr2 = [...arr1]; // const [...cArr3] = arr3; // const cArr4 = [...arr1, ...arr2, ...arr3]; // function *g() {生成器函数 // console.log(1); // yield 'hi~';//让函数暂停 // console.log(2); // yield 'imooc~'; // } // // const arr = [...g()];//arr = ['hi~','imooc~'] // const gg = g(); // gg.next();//生成器函数只能通过next()调用,并且执行到yield停止,要继续执行需要继续调用next()。 // setTimeout(function() { // gg.next(); // }, 1000); let set = new Set([1, 2, 2, 3]);es6中新的数据结构:集合。返回一个对象,接收一个数组,数组元素值不能重复,将会自动只保留一个。 console.log([...set]);
// 新的方法 // ---------------------------------------- // Array.from//将类数组对象转化为数组。 // const obj = { // 0: 1, // 1: '22', // 2: false, // length: 2//会根据长度取舍属性 // }; // console.log(Array.from(obj, item => item * 2));第二个参数为回调函数,将会设置得到计算后的值为属性值 // Array.prototype.slice.call(); // [].slice.call(); // [...] // ---------------------------------------- // Array.of//将所有参数按序生成数组。 // console.log(Array.of(1, 2, '123', false)); // ---------------------------------------- // Array#fill//填充,第一个参数为填充的值,并且会覆盖之前拥有的值,除非设置范围,第二个和第三个为开始和结束的索引。 // let arr = new Array(10).fill(0, 0, 3); // console.log([1, 2, 3].fill(0)); // ---------------------------------------- // Array.includes//数组中是否包含某一项,返回布尔值,有返回true // var arr = [1, 2, 3, 4]; // console.log(arr.includes(1)); // console.log(arr.includes(55)); // ---------------------------------------- // keys // const arr = [1, 2, 3, 444]; // console.log(arr.keys()); // for (let i of arr.keys()) { // console.log(i); // } // values // for (let v of arr.values()) { // console.log(v); // } // entries // for (let [i, v] of arr.entries()) { // console.log(i, v); // } // ---------------------------------------- // find 根据条件(回调) 按顺序遍历数组 当回调返回true时 就返回当前遍历到的值 // const res = [1, 7, 6, 3].find((value, index, arr) => value % 2 === 0); // console.log(res); // ---------------------------------------- // findIndex 根据条件(回调) 按顺序遍历数组 当回调返回true时 就返回当前遍历到的下标 const res = [1, 7, 6, 3, NaN].findIndex((value, index, arr) => Number.isNaN(value)); arr.indexOf(NaN)这个方法不能找到数组中的NaN,但上方可以在回调中设置条件,可以查找到。 console.log(res);
注意:
类数组对象的属性名必须为数值型或字符串型的数字,要将一个类数组对象转换为一个真正的数组,必须具备以下条件:
1、该类数组对象必须具有length属性,用于指定数组的长度。如果没有length属性,那么转换后的数组是一个空数组
2、该类数组对象的属性名必须为数值型或字符串型的数字
该类数组对象的属性名可以加引号,也可以不加引号