前言
本文记录JavaScript的高级语法,和ES6新增语法。
一点介绍
面向过程:就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候再一个一个的依次调用就可以了;按照我们分析好了的步骤,按照步骤解决问题。
面向对象:是把事务分解成为一个个对象,然后由对象之间分工与合作,是以对象功能来划分问题。
类和对象
类抽象了对象的公共部分,它泛指某一大类(class)
对象特指某一个,通过类实例化一个具体的对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86
| class Star { constructor(uname, age) { this.uname = uname; this.age = age; } sing() { console.log(999) } }
var ldh = new Star('刘德华', 18); var zxy = new Star('张学友', 20); console.log(ldh); console.log(zxy);
class Father { constructor() {} money() {console.log(100)} } class Son extends Father {} var son = new Son(); son.money()
class Father { constructor(x, y) { this.x = x; this.y = y; } sum() { return this.x + this.y; } } class Son extends Father { constructor(x, y) { super(x, y) } sum() { console.log(super.sum() + 'Son'); } } var son = new Son(1, 2); son.sum();
class Father { constructor(x, y) { this.x = x; this.y = y; } sum() { console.log(this.x + this.y); } }
class Son extends Father { constructor(x, y) { super(x, y); this.x = x; this.y = y; } subtract() { console.log(this.x - this.y); } } var son = new Son(5, 3); son.subtract(); son.sum();
|
class的其他属性
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| class Animal { static eat(name) { return console.log(name) } }
Animal.eat('猫');
class Phone { get price() { console.log("价格属性被读取了"); return '返回值'; }
set price(newVal) { console.log(newVal) console.log('价格属性被修改了'); } }
let s = new Phone(); let result = s.price console.log(result) s.price = 'free';
|
注意:this指向
在 ES6 中类没有变量提升,所以必须先定义类,才能通过类实例化对象.
类里面的共有属性和方法一定要加this使用.
类里面的this指向问题.
constructor里面的this指向实例对象, 方法里面的this 指向这个方法的调用者
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| <button>点击</button> var that; class Star { constructor(uname, age) { that = this; this.uname = uname; this.btn = document.querySelector('button'); this.btn.onclick = this.sing.bind(this); } sing() { console.log(this.uname); } }
var ldh = new Star('刘德华'); console.log(that === ldh);
|
apply、call与bind
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| window.color = "red"; var o = {color: "blue"}
function sayColor() { console.log(this.color); }
sayColor.call(window); sayColor.call(o); sayColor.apply(o);
call(thisObj, arg1, arg2, arg3, arg4); apply(thisObj, [args]);
window.color = "red"; var o = {color: "blue"}
var sayColor = function () { console.log(this.color); }.bind(o)
sayColor();
const fn = function(){}.bind() fn(xx,xx)
|
1 2 3 4 5 6 7 8 9 10 11 12 13
| function a() { console.log(1); }
var btn = document.querySelector('button')
btn.onclick = a()
btn.onclick = a
btn.onclick = function () { a() }
|
Json格式的转化
1 2 3 4 5 6 7 8 9
| var obj = {name: 'Q', age: 18} var strJson = JSON.stringify(obj) var newObj = JSON.parse(strJson)
let a = '["1","2"]'; let b = "['1','2']"; console.log(JSON.parse(a)); console.log(JSON.parse(b));
|
构造函数和原型导读
构造函数
构造函数的成员:实例成员-静态成员。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| function Star(uname, age) { this.uname = uname; this.age = age; this.sing = function() { console.log('我会唱歌');
} } var ldh = new Star('刘德华', 18);
console.log(ldh.uname); ldh.sing();
Star.sex = '男';
console.log(Star.sex); console.log(ldh.sex);
|
注意:构造函数每次实例化生成的函数会开辟新的内存来储存,造成存在浪费内存的问题
解决:采用prototype。
原型:prototype
构造函数通过原型分配的函数是所有对象所共享的。
1 2 3 4 5 6
| Star.prototype.sing = function() { console.log('我会唱歌'); } ldh.sing();
|
对象原型 proto
1 2 3 4 5 6
| console.log(ldh.__proto__)
console.log(ldh.__proto__ === Star.prototype);
|
原型的constructor构造函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
|
console.log(Star.prototype.constructor === Star.constructor)
Star.prototype = { constructor: Star, sing: function() { console.log('我会唱歌'); }, movie: function() { console.log('我会演电影'); } }
|
原型链

成员查找规则:
当访问一个对象的属性(包括方法)时,首先查找这个对象自身有没有该属性。
如果没有就查找它的原型(也就是 __proto__指向的 prototype 原型对象)。
如果还没有就查找原型对象的原型(Object的原型对象)。
依此类推一直找到 Object 为止(null)。
__proto__对象原型的意义就在于为对象成员查找机制提供一个方向,或者说一条路线。
构造函数的继承
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
|
function Father(uname) { this.uname = uname; } Father.prototype.money = function() { console.log(100000);
};
function Son(uname, score) { Father.call(this, uname); this.score = score; }
Son.prototype = new Father();
Son.prototype.constructor = Son;
Son.prototype.exam = function() { console.log('孩子要考试'); } var son = new Son('刘德华', 100); console.log(son); console.log(Father.prototype); console.log(Son.prototype.constructor);
|
JavaScript中的新增方法
数组方法
迭代(遍历)方法:forEach()、map()、filter()、some()、every();
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| array.forEach(function(currentValue,index, arr){
arr1[index] = item/2; })
var arr = array.map(function(currentValue,index, arr){
return currentValue % 2; })
var arr = array.filter(function(currentValue,index, arr){
return currentValue % 2 === 0; })
var flag = array.some(function(currentValue,index, arr){
return currentValue == 'xxx';
})
|
字符串方法
trim()方法会从一个字符串的两端删除空白字符。
对象方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
|
var o = { a: 1, b: 2 } console.log(Object.keys(o))
Object.defineProperty(obj,prop, descriptor)
delete obj.a;
|
函数进阶
函数的定义方式
1 2 3 4 5 6 7 8 9 10
| function fn() {};
var fun = function() {};
var f = new Function('a', 'b', 'console.log(a + b)'); f(1, 2);
console.log(x instanceof Object)
|
函数的调用方式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| function fn() { console.log('人生的巅峰');
}
var o = { sayHi: function() { console.log('人生的巅峰');
} } o.sayHi();
function Star() {}; new Star();
(function() { console.log('人生的巅峰'); })();
|
改变函数this指向
常用的有 bind()、call()、apply() 三种方法。
call方法调用一个对象,可以改变函数的this指向。
1 2 3 4 5 6 7 8 9 10
| var o = { name: 'andy' }
function fn(a, b) { console.log(this); console.log(a + b); }; fn.call(o, 1, 2);
|
apply方法,参数必须是数组(伪数组)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| var o = { name: 'andy' };
function fn(arr) { console.log(this); console.log(arr);
}; fn.apply(o, ['pink']);
var arr = [1, 66, 3, 99, 4]; var max = Math.max.apply(null, arr); var max = Math.max.apply(Math, arr); var max = Math.max(...arr)
|
bind方法不会调用函数,改变函数内部this 指向
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
|
btn.onclick = function () { console.log(this) setTimeout(function () { console.log(this) }.bind(this), 1000) setTimeout(() => { console.log(this) }, 1000) }
function f(that) { console.log(this) console.log(that) } btn.onclick = f.bind(btn,window)
|
严格模式
JavaScript除正常模式外,还有严格模式(strict mode),在严格的条件下运行 JS 代码。
严格模式有两种情况,应用到整个脚本或个别函数中。
1 2 3 4 5 6 7 8 9 10
| <script> 'use strict'; </script>
<script> (function() { 'use strict'; })(); </script>
|
严格模式的规范
变量规定
我们的变量名必须先声明再使用。
我们不能随意删除已经声明好的变量,delete num。
this 指向问题
严格模式下全局作用域中函数中的 this 是 undefined。
严格模式下,如果构造函数不加new调用, this指向的是undefined 如果给他赋值则会报错。
定时器this还是指向window。
函数变化
- 严格模式下函数里面的参数不允许有重名。
- if、for里面不写声明函数。
更多参考:严格模式 - JavaScript | MDN (mozilla.org)
高阶函数
高阶函数是对其他函数进行操作的函数,它接收函数作为参数或将函数作为返回值输出。
1 2 3 4 5
| function f(callBack) {callBack()} function f1() {console.log(1)}
function f() {return function f1() {console.log(1)}}
|
闭包
闭包(closure)指有权访问另一个函数作用域中变量的函数。
主要作用:延伸了变量的作用范围。
1 2 3 4 5 6 7 8 9 10 11 12
| function f() { var num = 1 return function () { return num } }
var num = f()() console.log(num) num = null console.log(num)
|
for循环是同步,而点击则是异步,里面的i已经是之后的值了。
1 2 3 4 5 6 7 8 9 10 11
| for (var i = 0; i < lis.length; i++) { (function(i) { lis[i].onclick = function() { console.log(i); } })(i); }
|
递归函数
如果一个函数在内部可以调用其本身,那么这个函数就是递归函数。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
| var num = 1; function fn() { console.log(1); if (num === 2) { return } num++; fn(); } fn();
function fn(n) { if (n == 1) { return 1; } return n + fn(n - 1); }
function x(n) { if (n === 1 || n === 2) { return 1; } return x(n - 1) + x(n - 2); }
var data = [ {id: 1, name: "我是爸爸1", parent_id: 0}, {id: 2, name: "我是爸爸2", parent_id: 0}, {id: 3, name: "我是儿子3", parent_id: 1}, {id: 4, name: "我是孙子4", parent_id: 3}, {id: 5, name: "我是重孙5", parent_id: 4}, {id: 6, name: "我是儿子6", parent_id: 2}, {id: 7, name: "我是孙子7", parent_id: 6}, {id: 8, name: "我是重孙8", parent_id: 7}, {id: 9, name: "我是爸爸9", parent_id: 0}, {id: 10, name: "我是儿子10", parent_id: 9}, {id: 11, name: "我是孙子11", parent_id: 10}, {id: 12, name: "我是儿子12", parent_id: 1} ];
function tree(x) { let treeArr = [] data.filter(item => { return item.parent_id === x; }).forEach(item => { treeArr.push( { id: item.id, label: item.name, children: tree(item.id) } ) }) return treeArr }
console.log(tree(0))
|
深拷贝与浅拷贝
浅拷贝只是拷贝一层, 更深层次对象级别的只拷贝引用。
1 2 3 4 5 6 7 8 9 10
| var obj1 = {a: 1} var obj2 = Object.assign({}, obj1); obj2.a = 2; console.log(obj1,obj2);
var arr1 = [{a: 1}, {b: 2}] var arr2 = Object.assign([], arr1); arr2[0] = {c: 3} console.log(arr1, arr2);
|
深拷贝拷贝多层, 每一级别的数据都会拷贝。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
|
var obj = { a: 1, b: { c: 2 } } var o = JSON.parse(JSON.stringify(obj)); o.b.c = 3 console.log(obj,o)
function deepClone(target) { let result; if (typeof target === 'object') { if (Array.isArray(target)) { result = []; for (let i in target) { result.push(deepClone(target[i])) } } else if (target === null) { result = null; } else if (target.constructor === RegExp) { result = target; } else { result = {}; for (let i in target) { result[i] = deepClone(target[i]); } } } else { result = target; } return result; }
|
正则表达式
正则表达式( Regular Expression )是用于匹配字符串中字符组合的模式。在JavaScript中,正则表达式也是对象。
创建正则表达式
1 2 3 4 5 6 7
| var regexp = new RegExp(/123/);
var rg = /123/;
|
测试正则表达式test
test() 正则对象方法,用于检测字符串是否符合该规则,该对象会返回 true 或 false,其参数是测试字符串。
1 2 3
| console.log(rg.test(123)); console.log(rg.test('abc'));
|
正则表达式的组成
正则表达式可由简单和特殊字符组合,比如 /ab*c/,特殊字符称为元字符,如 ^ 、$ 、+ 。
正则表达相关链接
正则表达式中的特殊字符
1.边界符
正则表达式中的边界符(位置符)用来提示字符所处的位置,主要有两个字符。

1 2 3 4 5 6
|
var reg = /^abc$/; console.log(reg1.test('abc')); console.log(reg1.test('abcd')); console.log(reg1.test('abcabc'));
|
2.字符类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| var rg = /[abc]/;
console.log(rg.test('andy')); console.log(rg.test('red'));
var rg1 = /^[abc]$/;
console.log(rg1.test('a')); console.log(rg1.test('aa')); console.log(rg1.test('abc'));
var reg = /^[a-z]$/;
console.log(reg.test('a')); console.log(reg.test(1)); console.log(reg.test('A'));
var reg1 = /^[a-zA-Z0-9_-]$/; console.log(reg1.test(8)); console.log(reg1.test('!'));
var rg = /^[^a-zA-Z0-9]$/ console.log(rg.test('!'))
|
3.量词符
量词符用来设定某个模式出现的次数。

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| var reg = /^a*$/; console.log(reg.test('')); console.log(reg.test('a')); console.log(reg.test('aaaa'));
var reg = /^a+$/; console.log(reg.test('')); console.log(reg.test('a')); console.log(reg.test('aaaa'));
var reg = /^a?$/; console.log(reg.test('')); console.log(reg.test('a')); console.log(reg.test('aaaa'));
var reg = /^a{3}$/; console.log(reg.test('aaa')); console.log(reg.test('aaaa'));
var reg = /^a{3,}$/; console.log(reg.test('a')); console.log(reg.test('aaa'));
var reg = /^a{3,6}$/; console.log(reg.test('a')); console.log(reg.test('aaa'));
|
4.括号总结
1 2 3 4 5 6 7 8 9
| var reg = /^abc{3}$/;
console.log(reg.test('abcabcabc')); console.log(reg.test('abccc'));
var reg = /^(abc){3}$/; console.log(reg.test('abcabcabc')); console.log(reg.test('abccc'));
|
5.预定义类
预定义类指的是某些常见模式的简写方式。

1 2 3
|
var reg = /^\d{3}-\d{8}|\d{4}-\d{7}$/;
|
正则替换
正则表达式参数:/表达式/[switch],有三种值:
- g:全局匹配
- i:忽略大小写
- gi:全局匹配 + 忽略大小写
1 2 3 4
| btn.onclick = function() { div.innerHTML = text.value.replace(/a|b/g, '**'); }
|
ES6新增
ES6实际上是一个泛指,泛指ES2015及后续的版本。
声明变量的关键字
let关键字
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| if (true) { var a = 1; let b = 2 } console.log(a) console.log(b)
for (let i = 0; i < 2; i++) {} console.log(i);
console.log(a) let a = 1
var num = 10 if (true) { console.log(num); let num = 20; }
|
const关键字
声明常量,常量就是值(内存地址)不能变化的量。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| if (true) { const a = 10; } console.log(a);
const PI = 3.14;
const PI = 3.14; PI = 100; const o = {a: 1}; o = {a: 2} o.a = 2
|
var、let、const区别
| var |
let |
const |
| 函数级作用域 |
块级作用域 |
块级作用域 |
| 变量提升 |
不存在变量提升 |
不存在变量提升 |
| 值可更改 |
值可更改 |
值不可更改 |
解构赋值
数组解构
1 2 3 4 5 6 7 8
| let ary = [1,2,3]; let [a, b, c] = ary; console.log(a,b,c)
let [d] = []; let [d, f] = [1];
|
对象解构
1 2 3 4 5 6 7 8 9
| let o = {a: 1, b: 2} let {a, b} = o console.log(a, b)
let o = {a: 1, b: 2} let {a: c, b: d} = o console.log(c, d)
|
箭头函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| const fn = () => { console.log(123) } fn();
const sum = (n1, n2) => n1 + n2; const result = sum(10, 20); console.log(result)
const fn = v => { alert(v); } fn(20)
|
箭头函数不绑定this关键字
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| function fn () { console.log(this); return () => { console.log(this) } } const obj = {name: 'moxie'}; const resFn = fn.call(obj); resFn()
const obj = { fn: () => { console.log(this) }, } obj.fn()
function f() { const obj = { fn: () => { console.log(this) } } obj.fn() } f.call({})
|
箭头函数剩余参数
剩余参数是实参大于形参,箭头函数没有arguments
1 2 3 4 5 6
| const fn = (...args) => { console.log(args) }; fn(10, 20, 30)
|
拓展运算符
扩展运算符...可以将数组或者对象转为用逗号分隔的参数序列。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73
|
let ary = [1, 2, 3]
console.log(...ary) console.log(1, 2, 3)
const arr1 = [1, 2, 3] console.log(Math.min(...arr1)) console.log(Math.max(...arr1))
const arr1 = [1,2,3]; const arr2 = [...arr1]; console.log(arr2);
const arr1 = [1, 2, 3] const arr2 = [4, 5, 6] console.log([...arr1, ...arr2]) console.log(arr1.concat(arr2))
arr1.push(...arr2) console.log(arr1)
let arr = ['a', 'b']; arr = [...arr, 'c']; console.log(arr);
var oDivs = document.getElementsByTagName('div'); var ary = [...oDivs]; ary.push('a'); console.log(ary);
let obj = { a: 1, b: 2 }; obj = {...obj, c: 3}; console.log(obj)
let str = 'abc'
console.log(...str) console.log('a','b','c')
const str = 'abc'; const arr = [...str]; console.log(arr);
const obj = {a: 1, b: 2, c: 3} const {a, ...rest} = obj; console.log(a, rest);
const arr = [1, 2, 3] const [a,...rest] = arr; console.log(a, rest);
|
Array 的扩展方法
- Array.from()将类数组或可遍历对象转换为真正的数组
1 2 3 4 5 6 7 8 9
| var arr = { "0": "1", "1": "2", "length": 2 }
var arr1 = Array.from(arr, item => item * 2) console.log(arr1)
|
- Array.find()用于找出第一个符合条件的数组成员,返回为当前成员,如果没有找到返回undefined
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| var ary = [ { id: 1, name: '张三' }, { id: 2, name: '李四' }, { id: 1, name: '王五' } ]; let target = ary.find(item => item.id === 1); console.log(target)
let arr1 = ary.filter(item => item.id === 1) console.log(arr1)
|
- Array.findIndex()用于找出第一个符合条件的数组成员的位置,如果没有找到返回-1
1 2 3
| let ary = [10, 20, 50]; let index = ary.findIndex(item => item > 15); console.log(index)
|
- Array.includes()表示某个数组是否包含给定的值,返回布尔值。
1 2 3
| let ary = ["a", "b", "c"]; let result = ary.includes('a') console.log(result)
|
String 的扩展方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| let str = 'b'; let str1 = `a${str}`; console.log(str1)
let str = `第一行 第二行` console.log(str)
const fn = () => { return '我是fn函数' }
let html = `我是模板字符串 ${fn()}`; console.log(html)
|
- startsWith() 和 endsWith()
1 2 3 4 5
|
let str = 'Hello world!'; console.log(str.startsWith('Hello')) console.log(str.endsWith('!'))
|
- repeat()方法表示将原字符串重复n次,返回一个新字符串。
1
| console.log("y".repeat(5))
|
Set 数据结构
ES6提供了新的数据结构Set。它类似于数组,但是成员的值都是唯一的,没有重复的值。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
| const s1 = new Set([1,2]);
console.log(s1.size)
const s3 = new Set(["a","a","b","b"]); const ary = [...s3]; console.log(ary)
const s4 = new Set();
s4.add('a').add('b'); console.log(s4.size)
const s4 = new Set(['a', 'b']); const r1 = s4.delete('a'); console.log(s4.size) console.log(r1);
const s4 = new Set(['a', 'b']); const r2 = s4.has('c'); console.log(r2)
s4.clear(); console.log(s4.size);
const s5 = new Set(['a', 'b', 'c']); s5.forEach(value => { console.log(value) })
|
Map数据结构
类似于对象,键名可以是各种类型的值,Map实现 iterator接口,可以使用...和for of进行遍历。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| let m = new Map();
m.set('name', 'root');
let key = { name: 'admin' };
m.set(key, [1, 2]);
console.log(m.size);
for (let v of m) { console.log(v); }
m.delete('name');
console.log(m.get(key));
m.clear();
|
简化对象的写法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
|
let name = 'moxie'; let change = function(){ console.log('我们可以改变你!!'); }
const obj = { name, change, improve(){ console.log("我们可以提高你的技能"); } } console.log(obj);
|
函数的默认参数
1 2 3 4 5 6 7 8 9 10 11 12 13 14
|
function add(a, b, c = 3) { return a + b + c; }
console.log(add(1, 2));
function fn({a, b, c: d = 3}) { console.log(a, b, d) }
fn({a: 1, b: 2})
|
Symbol
ES6 引入了一种新的原始数据类型 Symbol,表示独一无二的值。它是 JavaScript 语言的第七种数据类型,是一种类似于字符串的数据类型。
特点
- Symbol 的值是唯一的,用来解决命名冲突的问题
- Symbol 值不能与其他数据进行运算
- Symbol 定义的对象属性不能使用
for…in 循环遍历,但是可以使用 Reflect.ownKeys 来获取对象的所有键名
1 2 3 4 5 6 7 8 9 10 11 12
| let s = Symbol('moxie'); let s1 = Symbol('moxie'); console.log(typeof s) console.log(s === s1)
let s2 = Symbol.for('默谐'); let s3 = Symbol.for('默谐'); console.log(s2 === s3)
|
Symbol的使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
|
let obj = { uname: function () { console.log('初始内容') }, }; let uname = Symbol('uname') obj[uname] = function () { console.log('追加的内容') } obj['uname']() obj[uname]()
let obj = { uname: function () { console.log('初始内容') }, [uname = Symbol('uname')]: function () { console.log("追加的内容") }, }; obj['uname']() obj[uname]()
|
Symbol 内置值
|
|
Symbol.hasInstance |
当其他对象使用 instanceof 运算符,判断是否为该对 象的实例时,会调用这个方法 |
Symbol.isConcatSpreadable |
对象的 Symbol.isConcatSpreadable 属性等于的是一个 布尔值,表示该对象用Array.prototype.concat()时, 是否可以展开。 |
Symbol.species |
创建衍生对象时,会使用该属性 |
Symbol.match |
当执行 str.match(myObject) 时,如果该属性存在,会 调用它,返回该方法的返回值。 |
Symbol.replace |
当该对象被 str.replace(myObject)方法调用时,会返回 该方法的返回值。 |
Symbol.search |
当该对象被 str.search (myObject)方法调用时,会返回 该方法的返回值。 |
Symbol.split |
当该对象被 str.split (myObject)方法调用时,会返回该 方法的返回值。 |
Symbol.iterator |
对象进行 for...of 循环时,会调用 Symbol.iterator 方法, 返回该对象的默认遍历器 |
Symbol.toPrimitive |
该对象被转为原始类型的值时,会调用这个方法,返 回该对象对应的原始类型值。 |
Symbol. toStringTag |
在该对象上面调用 toString 方法时,返回该方法的返 回值 |
Symbol. unscopables |
该对象指定了使用 with 关键字时,哪些属性会被 with 环境排除。 |
迭代器
遍历器Iterator一种接口,用来访问不同数据结构。任何数据结构只要部署 Iterator 接口,就可以完成遍历操作。
ES6 创造了一种新的遍历命令 for...of 循环,Iterator 接口主要供 for...of遍历。
- 原生具备
iterator 接口的数据(可用 for of 遍历),Array、Arguments 、Set 、Map 、String 、TypedArray 、NodeList
- 工作原理
- 创建一个指针对象,指向当前数据结构的起始位置
- 第一次调用对象的 next 方法,指针自动指向数据结构的第一个成员
- 接下来不断调用 next 方法,指针一直往后移动,直到指向最后一个成员
- 每调用 next 方法返回一个包含 value 和 done 属性的对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| const arr = ['a', 'b']; for (let v of arr) { console.log(v); }
let iterator = arr[Symbol.iterator]();
console.log(iterator.next()); console.log(iterator.next()); console.log(iterator.next());
const user = { name: "默谐", stus: [ 'a', 'b', ], [Symbol.iterator]() { let index = 0; let _this = this; return { next: function () { if (index < _this.stus.length) { const result = { value: _this.stus[index], done: false }; index++; return result; }else{ return {value: undefined, done: true}; } } }; } } for (let v of banji) { console.log(v); }
|
生成器
生成器函数是 ES6 提供的一种异步编程解决方案,语法行为与传统函数完全不同。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
| function* fn(a, ...b) { console.log(a, b); let c = yield '分割' console.log(c); }
let iterator = fn(1, 2, 3); console.log(iterator.next());
console.log(iterator.next('使用next方法传递参数'));
function one() { setTimeout(() => { console.log(111); iterator.next(); }, 1000) }
function two() { setTimeout(() => { console.log(222); iterator.next(); }, 2000) }
function* gen() { yield one(); yield two(); }
let iterator = gen(); iterator.next();
|
promise
Promise 是 ES6 引入的异步编程的新解决方案。语法上 Promise 是一个构造函数, 用来封装异步操作并可以获取其成功或失败的结果。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
| const p = new Promise(function (resolve, reject) { setTimeout(function () { reject('失败'); }, 1000); });
p.then(function (value) { console.log(value); }, function (reason) { console.error(reason); })
p.catch(function (reason) { console.warn(reason); })
const p1 = new Promise((resolve) => { setTimeout(() => { console.log(1) resolve("2") }, 1000) })
var p2 = p1.then(res => { console.log(res) return new Promise((resolve) => { setTimeout(() => { resolve(3) },1000) }) }) p2.then((res)=>{ console.log(res) })
|
promise的使用及其他
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
| const fetchRequest = (url) => { return new Promise(async (resolve, reject) => { let response = await fetch(url); if (response.status === 200) { resolve(response); } else { reject('出错了'); } }) }
fetchRequest('xxx').then((response) => { console.log(response) }).catch((err) => { console.error(err) })
const onePromise = fetchRequest('xxx1') const twoPromise = fetchRequest('xxx2')
Promise.all([ onePromise, twoPromise ]).then((res) => { console.log(res) }).catch(err => { console.error(err) })
const threePromise = fetchRequest('xxx') const fourPromise = fetchRequest('xxx')
Promise.race([ threePromise, fourPromise ]).then((res) => { console.log(res) }).catch(err => { console.error(err) })
function f() { try { } catch (error) { console.error(error) } }
|
ES6模块化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
|
import * as m from "./xxx.js";
import {m1, m2} from "./xxx.js";
import {default as m3} from "./xxx.js";
import m from "./xxx.js";
import m as m3 from "./xxx.js";
|
模块化方式二
1 2 3 4 5 6
| import * as m1 from "./m1.js"; import * as m2 from "./m2.js"; import * as m3 from "./m3.js";
<script src="./app.js" type="module"></script>
|
防抖与节流
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
|
var input = document.querySelector("#input") var timer; input.onkeyup = function () {
clearTimeout(timer) timer = setTimeout(function () { console.log("开始执行搜索...") }, 1000); }
var input = document.querySelector("#input") var lastTime = 0; input.onkeyup = function () { var nowTime = new Date().getTime(); if (nowTime - lastTime > 3000) { console.log("开始执行搜索...") lastTime = nowTime; } }
|