赞
踩
ES6 是一种客户端脚本语言规范;(ES2015,ES2016,ES2017等,ES2015 则是正式名称,特指该年发布的正式版本的语言标准)
ES6 引入了块级作用域,明确允许在块级作用域之中声明函数。ES6 规定,块级作用域之中,函数声明语句的行为类似于let,在块级作用域之外不可引用。
const obj = {
name: 'xiecheng',
age: 34
}
obj.school = 'imooc'
console.log(obj)
// {name: "xiecheng", age: 34, school: "imooc"}
const 实际上保证的并不是变量的值不得改动,而是变量指向的那个内存地址所保存的数据不得改动。
如何让对象或者数组这种引用数据类型也不被改变呢?Object.freeze(obj)
注意 : Object.freeze() 只是浅层冻结,只会对最近一层的对象进行冻结,并不会对深层对象冻结。
Object.entries() 将对象中的键值对返回成一个数组;
Object.keys() 将对象中的键名返回成一个数组;
Object.values() 将对象中的值返回成一个数组;
let user = [{ name: 'John', age: 30 },{ name: 'Tom', age: 29 },{ name: 'Zoe', age: 25 }] console.log(" Object.entries(user):") console.log( Object.entries(user)) console.log(" Object.keys(user):") console.log( Object.keys(user)) console.log(" Object.values(user):") console.log( Object.values(user))
结果:
for (let [key, value] of Object.entries(user)) {
console.log(`${key}:`)
console.log(value) // name:John, then age:30
}
一、类数组对象:所谓类数组对象,最基本的要求就是具有length属性的对象。
二、Array.from()方法就是将一个类数组对象或者可遍历对象转换成一个真正的数组。
Array.from有三个参数,Array.from(arrayLike[, mapFn[, thisArg]]),
arrayLike:想要转换成数组的伪数组对象或可迭代对象;
mapFn:如果指定了该参数,新数组中的每个元素会执行该回调函数;
thisArg:可选参数,执行回调函数 mapFn 时 this 对象。该方法的返回值是一个新的数组实例(真正的数组)。
该类数组对象必须具有length属性,用于指定数组的长度。如果没有length属性,那么转换后的数组是一个空数组。
let arrLike = {
'name': 'name',
'age': 'age',
'sex': 'sex',
'user': ['user1','user2','user3'],
}
const array = Array.from(arrLike)
console.log(array) //[]
Array.from还可以接受第二个参数,作用类似于数组的map方法,用来对每个元素进行处理,将处理后的值放入返回的数组。如下:
let arr = [1,2,3,4,5,6,7,8,9]
let set = new Set(arr)
console.log(Array.from(set, item => item + 1)) // [2,3,4,5,6,7,8,9,10]
将字符串转换为数组
let str = 'hello world!';
console.log(Array.from(str)) // ["h", "e", "l", "l", "o", " ", "w", "o", "r", "l", "d", "!"]
将Map解构转为数组,最方便的做法就是使用扩展运算符(…)
const myMap = new Map().set(true, 7)
console.log(myMap); //Map(1) {true => 7}
console.log([...myMap]); //[true ,7]
Array.of() 方法创建一个具有可变数量参数的新数组实例,而不考虑参数的数量或类型。
Array.of() 和 Array 构造函数之间的区别在于处理整数参数:Array.of(7) 创建一个具有单个元素 7 的数组,而 Array(7) 创建一个长度为7的空数组(注意:这是指一个有7个空位(empty)的数组,而不是由7个undefined组成的数组)。
Array.of(7); // [7]
Array.of(1, 2, 3); // [1, 2, 3]
Array(7); // [ , , , , , , ]
Array(1, 2, 3); // [1, 2, 3]
fill() 方法用一个固定值填充一个数组中从起始索引到终止索引内的全部元素。不包括终止索引。
let array = [1, 2, 3, 4]
array.fill(0, 1, 2) //把 0 填充在索引为1开始,到索引为2结束,不包括终止索引
// [1,0,3,4]
fill 不具备遍历的功能,它是通过指定要操作的索引范围来进行,可以看出不指定索引会对所有元素进行操作
Array(5).fill(1)
// [1,1,1,1,1]
find() 方法返回数组中满足提供的测试函数的第一个元素的值,否则返回 undefined。
let array = [5, 12, 8, 130, 44];
let found = array.find(function(element) {
return element > 10;
});
console.log(found);
// 12
findIndex()方法返回数组中满足提供的测试函数的第一个元素的索引。否则返回-1。其实这个和 find() 是成对的,不同的是它返回的是索引而不是值。
let array = [5, 12, 8, 130, 44];
let found = array.find(function(element) {
return element > 10;
});
console.log(found);
// 1
在当前数组内部,将指定位置的成员复制到其他位置(会覆盖原有成员),然后返回当前数组。也就是说,使用这个方法,会修改当前数组。
let arr = [1, 2, 3, 4, 5]
console.log(arr.copyWithin(1, 3)
function sum(base, ...nums) {
let num = base
nums.forEach(function(item) {
num += item * 1
})
return num
}
console.log(sum(30, 1, 2, 3)) // 36
console.log(sum(30, 1, 2, 3, 4)) // 40
Spread Operator 和 Rest Parameter 是形似但相反意义的操作符,简单的来说 Rest Parameter 是把不定的参数“收敛”到数组,而 Spread Operator 是把固定的数组内容“打散”到对应的参数。示例如下:
function sum(x = 1, y = 2, z = 3) {
return x + y + z
}
console.log(sum(...[4])) // 9
console.log(sum(...[4, 5])) // 12
console.log(sum(...[4, 5, 6])) // 15
函数指定了默认值以后,函数的length属性,将返回没有指定默认值的参数个数。
function foo(x = 1, y = 2, z = 3) {
console.log(x, y)
}
foo(x = 1, y = 2, z = 3) console.log(foo.length) // 0
foo(x, y = 2, z = 3) console.log(foo.length) // 1
foo(x, y = 2, z) console.log(foo.length) // 1
foo(x, y, z = 3) console.log(foo.length) // 2
函数的name属性,返回该函数的函数名。
function foo() {}
foo.name // "foo"
如果返回值是表达式可以省略 return 和 {}
let pow = x => x * x
如果返回值是字面量对象,一定要用小括号包起来
let person = (name) => ({
age: 20,
addr: 'Beijing City'
})
function showDetail (string,...type){
console.log(string)
console.log(type)
}
const res = showDetail`答案是:${'A'},${'恭喜你答对了'}!`
let name = 'xiecheng'
let age = 34
let obj = {
name,
age,
study() {
console.log(this.name + '正在学习')
}
}
let s = 'second'
let obj = {
first: 'wu',
[s]: 'shuxuan'
}
console.log(obj) //{first: "wu", second: "shuxuan"}
let obj1 = { // new Object() name: 'xiecheng', age: 34 } let obj2 = { // new Object() name: 'xiecheng', age: 34 } console.log(obj1 == obj2) // false console.log(Object.is(obj1, obj2)) // false let obj2 = obj1 console.log(Object.is(obj1, obj2)) // true
const target = { a: 1, b: 2 } const source = { b: 4, c: 5 } const returnedTarget = Object.assign(target, source) console.log(target) // expected output: Object { a: 1, b: 4, c: 5 } console.log(returnedTarget) // expected output: Object { a: 1, b: 4, c: 5 }
如果目的对象不是对象,则会自动转换为对象
class 的方式是 function 方式的语法糖。
对于面向对象编程而言,更关注类的声明、属性、方法、静态方法、继承、多态、私有属性。
class Animal {
constructor(type) {
this.type = type
}
walk() {
console.log( `I am walking` )
}
}
let dog = new Animal('dog')
let monkey = new Animal('monkey')
class CustomHTMLElement {
constructor(element) {
this.element = element
}
get html() {
return this.element.innerHTML
}
set html(value) {
this.element.innerHTML = value
}
}
var cus = new CustomHTMLElement(document.getElementById('h2'))
console.log(cus)
let age = 50 class Animal { constructor(type) { this.type = type } get age() { return age } set age(val) { if (val > 0 && val < 10) { age = val }else{ age = 25 } } } var roobit = new Animal(20); roobit.age = 30; console.log(roobit)
工具类,比如自己写日期工具类,里面有 日期转换,获取前一天,后一天等方法。扩展方法必须是静态类
静态方法一般都是进行一系列比较单一的数据处理,这些数据往往都是由外部传过来,进行相应的操作后返回.他不需要维护比较复杂的生命周期,方法调用完后就跟他没什么关系了.
在同一个类里静态方法优先给他分配内存
当你在别的类调用的时候可以直接类名.方法,不用先实例化对象 再调用方法
经常要被调用时,就用静态的.相反则用非静态的
静态方法中只能调用静态成员或者方法,不能调用非静态方法或者非静态成员,而非静态方法既可以调用静态成员或者方法又可以调用其他的非静态成员或者方法。
class Animal {
constructor(type) {
this.type = type
}
walk() {
console.log( `I am walking` )
}
static eat() {
console.log( `I am eating` )
}
}
ES6 引入了一种新的原始数据类型 Symbol ,表示独一无二的值。它是 JavaScript 语言的第七种数据类型,前六种是:undefined、null、布尔值(Boolean)、字符串(String)、数值(Number)、对象(Object)。
let s1 = Symbol()
let s2 = Symbol()
// let s1 = Symbol('foo')
// let s2 = Symbol('foo')
console.log(s1)
console.log(s2)
console.log(s1 === s2) // false
Symbol.for()
接受一个字符串作为参数,然后搜索有没有以该参数作为名称的 Symbol 值。如果有,就返回这个 Symbol 值,否则就新建一个以该字符串为名称的 Symbol 值,并将其注册到全局。
let s1 = Symbol.for('foo')
let s2 = Symbol.for('foo')
console.log(s1 === s2) // true
Symbol.for()与Symbol()这两种写法,都会生成新的 Symbol。它们的区别是,前者会被登记在全局环境中供搜索,后者不会。Symbol.for()不会每次调用就返回一个新的 Symbol 类型的值,而是会先检查给定的key是否已经存在,如果不存在才会新建一个值。
Symbol.keyFor()方法返回一个已登记的 Symbol 类型值的key。
const s1 = Symbol('foo')
console.log(Symbol.keyFor(s1)) // undefined
const s2 = Symbol.for('foo')
console.log(Symbol.keyFor(s2)) // foo
const sym = Symbol('imooc') class User { constructor(name) { this.name = name this[sym] = 'imooc.com' } getName() { return this.name + this[sym] } } const user = new User('xiecheng') console.log(user.getName()) //xiechengimooc.com for (let key in user) { console.log(key) //name、 } for (let key of Object.keys(user)) { console.log(key) //name、 } for (let key of Object.getOwnPropertySymbols(user)) { console.log(key) //Symbol(imooc)、 } for (let key of Reflect.ownKeys(user)) { console.log(key) //name、Symbol(imooc) }
魔术字符串指的是,在代码之中多次出现、与代码形成强耦合的某一个具体的字符串或者数值。风格良好的代码,应该尽量消除魔术字符串,改由含义清晰的变量代替。 (case 后面加的字符串就是魔术字符串)
const shapeType = { triangle: Symbol(), circle: Symbol() } function getArea(shape) { let area = 0 switch (shape) { case shapeType.triangle: area = 1 break case shapeType.circle: area = 2 break } return area } console.log(getArea(shapeType.triangle))
ES6 提供了新的数据结构 Set。它类似于数组,但是成员的值都是唯一的,没有重复的值。
s.add('hello').add('goodbye')
// 删除指定数据
s.delete('hello') // true
// 删除全部数据
s.clear()
Set 可以快速进行统计数据,如数据是否存在、数据的总数。
// 判断是否包含数据项,返回 true 或 false
s.has('hello') // true
// 计算数据项总数 => 相当于数组的长度
s.size // 2
let arr = [1, 2, 3, 4, 2, 3]
let s = new Set(arr)
console.log(s) //[1,2,3,4]
let arr1 = [1, 2, 3, 4]
let arr2 = [2, 3, 4, 5, 6]
let s = new Set([...arr1,...arr2])
console.log(s)
console.log([...s]) //set转array
console.log(Array.from(s)) //set转array
let s1 = new Set(arr1)
let s2 = new Set(arr2)
let result = new Set(arr1.filter(item => s2.has(item)))
console.log(Array.from(result))
let arr1 = [1, 2, 3, 4]
let arr2 = [2, 3, 4, 5, 6]
let arr3 = new Set(arr1.filter(item => !new Set([2, 3, 4, 5, 6]).has(item)))
let arr4 = new Set(arr2.filter(item => !new Set([1, 2, 3, 4]).has(item)))
console.log(arr3) //[1]
console.log(arr4) //[5,6]
console.log([...arr3, ...arr4]) //[1,5,6]
WeakSet 结构与 Set 类似,也是不重复的值的集合。但是,它与 Set 有两个区别。
WeakSet 的成员只能是对象,而不能是其他类型的值。
let ws = new WeakSet()
const obj1 = {
name: 'imooc'
}
const obj2 = {
age: 5
}
ws.add(obj1)
ws.add(obj2)
ws.delete(obj1)
console.log(ws)
console.log(ws.has(obj2))
WeakSet 没有size属性,没有办法遍历它的成员。
WeakSet 中的对象都是弱引用,即垃圾回收机制不考虑 WeakSet 对该对象的引用,也就是说,如果其他对象都不再引用该对象,那么垃圾回收机制会自动回收该对象所占用的内存,不考虑该对象还存在于 WeakSet 之中。
ES6 提供了 Map 数据结构。它类似于对象,也是键值对的集合,但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键。也就是说,Object 结构提供了“字符串—值”的对应,Map 结构提供了“值—值”的对应,是一种更完善的 Hash 结构实现。如果你需要“键值对”的数据结构,Map 比 Object 更合适。
let map = new Map([iterable])
Iterable 可以是一个数组或者其他 iterable 对象,其元素为键值对(两个元素的数组,例如: [[ 1, ‘one’ ], [ 2, ‘two’ ]])。 每个键值对都会添加到新的 Map。null 会被当做 undefined。
let keyObj = {}
let keyFunc = function() {}
let keyString = 'a string'
// 添加键
map.set(keyString, "和键'a string'关联的值")
map.set(keyObj, '和键keyObj关联的值')
map.set(keyFunc, '和键keyFunc关联的值')
// 删除指定的数据
map.delete(keyObj)
// 删除所有数据
map.clear()
// 统计所有 key-value 的总数
console.log(map.size) //2
// 判断是否有 key-value
console.log(map.has(keyObj)) // true
get() 方法返回某个 Map 对象中的一个指定元素
console.log(map.get(keyObj)) // 和键keyObj关联的值
WeakMap结构与Map结构类似,也是用于生成键值对的集合。
// WeakMap 可以使用 set 方法添加成员 const wm1 = new WeakMap() const key = { foo: 1 } wm1.set(key, 2) wm1.get(key) // 2 // WeakMap 也可以接受一个数组, // 作为构造函数的参数 const k1 = [1, 2, 3] const k2 = [4, 5, 6] const wm2 = new WeakMap([ [k1, 'foo'], [k2, 'bar'] ]) wm2.get(k2) // "bar"
WeakMap与Map的区别有两点。
const map = new WeakMap()
map.set(1, 2)
// TypeError: 1 is not an object!
map.set(Symbol(), 2)
// TypeError: Invalid value used as weak map key
map.set(null, 2)
// TypeError: Invalid value used as weak map key
总结:
var newMap = new Map();
newMap.set("json",{name:'123',age:18});
newMap.set("null_json",{});
newMap.set("string","456");
console.log(newMap)
newMap.delete('null_json')
console.log(newMap)
console.log(newMap.size)
console.log(newMap.get("string"))
y 修饰符的作用与 g 修饰符类似,也是全局匹配,后一次匹配都从上一次匹配成功的下一个位置开始。
不同之处在于**,g 修饰符只要剩余位置中存在匹配就可,而 y 修饰符确保匹配必须从剩余的第一个位置开始**
let str = "ccc_cc_c"
let a1 = /c+/g
let a2 = /c+/y
console.log(a1.exec(str)) //ccc
console.log(a2.exec(str)) //ccc
console.log("=================")
console.log(a1.exec(str)) //cc
console.log(a2.exec(str)) //null
ES5不支持四个字节的 UTF-16 编码,会将其识别为两个字符
u 用来正确处理大于 \uFFFF 的Unicode字符
如何把十进制转化为二进制?
const a = 5 // 101
console.log(a.toString(2))
如何把八进制转化为二进制?
const b = 101
console.log(parseInt(b, 2))
ES6 提供了二进制和八进制数值的新的写法,分别用前缀0b(或0B)和0o(或0O)表示。
const a = 0B0101
console.log(a)
const b = 0O777
console.log(b)
// ES5的写法
parseInt('12.34') // 12
// ES6的写法
Number.parseInt('12.34') // 12
Math.pow(2, 53) // 9007199254740992
Math.pow(2, 53) === Math.pow(2, 53) + 1 // true
Number.MAX_SAFE_INTEGER === Math.pow(2, 53) - 1 // true
Number.MAX_SAFE_INTEGER === 9007199254740991 // true
Number.MIN_SAFE_INTEGER === -Number.MAX_SAFE_INTEGER // true
Number.MIN_SAFE_INTEGER === -9007199254740991 // true
方法用来判断一个数到底是正数、负数、还是零。对于非数值,会先将其转换为数值。
它会返回五种值。
参数为正数,返回+1
参数为负数,返回-1
参数为 0,返回0
参数为-0,返回-0
其他值,返回NaN
在 ES6 标准中新增的一个非常强大的功能是 Proxy,它可以自定义一些常用行为如查找、赋值、枚举、函数调用等。通过 Proxy 这个名称也可以看出来它包含了“代理”的含义,只要有“代理”的诉求都可以考虑使用 Proxy 来实现。
//监听报错 window.addEventListener('error',(e)=>{ console.log(e) },true) let o = { name: 'xiaoming', age: 40 } let validator = (obj,key,value)=>{ if(Reflect.has(obj,key)){ if(value>30){ obj[key] = value }else{ //不满足则触发错误 throw new TypeError('age error') // return false; } } } let handler = { //读操作 get (obj, key) { return Reflect.has(obj, key) ? obj[key] : '没有该属性' }, //写操作 set : validator } let p = new Proxy(o,handler) p.age = 15 console.log(p) console.log(p.age)
let handler = {
//读操作
get (obj, key) {
return Reflect.has(obj, key) ? obj[key] : '没有该属性'
},
}
let p = Proxy.revocable(o,handler)
p.age = 15
p.revoke(); //撤销
同步:只有前一个任务执行完毕,才能执行后一个任务
异步:当同步任务执行到某个 WebAPI 时,就会触发异步操作,此时浏览器会单独开线程去处理这些异步任务。
Promise.reject(error) 是和 Promise.resolve(value) 类似的静态方法,是 new Promise() 方法的快捷方式。
function getPromise(url) { return new Promise((resolve, reject) => { ajax(url, res => { resolve(res) }, err => { reject(err) }) }) } getPromise('static/a.json') .then(res => { console.log(res) return getPromise('static/b.json') }).then(res => { console.log(res) return getPromise('static/c.json') }).then(res => { console.log(res) }).catch(err => { console.log(err) })
var p1 = Promise.resolve(1)
var p2 = Promise.resolve(2)
var p3 = Promise.resolve(3)
Promise.all([p1, p2, p3]).then(function(results) {
console.log(results) // [1, 2, 3]
})
var p1 = Promise.resolve(1)
var p2 = Promise.resolve(2)
var p3 = Promise.resolve(3)
Promise.race([p1, p2, p3]).then(function(value) {
console.log(value) // 1
})
Reflect.apply(target, thisArgument, argumentsList)
Reflect.apply(Math.floor, undefined, [1.75])
// 1
Reflect.apply(String.fromCharCode, undefined, [104, 101, 108, 108, 111])
// "hello"
Reflect.apply(RegExp.prototype.exec, /ab/, ['confabulation']).index
// 4
Reflect.apply(''.charAt, 'ponies', [3])
// "i"
Reflect.construct() 方法的行为有点像 new 操作符 构造函数 , 相当于运行 new target(…args).
Reflect.construct(target, argumentsList[, newTarget])
var d = Reflect.construct(Date, [961223754000])
console.log(d instanceof Date) // true
console.log(d.getFullYear() )// 2000
如果使用 newTarget 参数,则表示继承了 newTarget 这个超类:
function someConstructor() {}
var result = Reflect.construct(Array, [], someConstructor)
Reflect.getPrototypeOf(result) // 输出:someConstructor.prototype
Array.isArray(result) // true
静态方法 Reflect.defineProperty() 基本等同于 Object.defineProperty() 方法,唯一不同是返回 Boolean 值。
Reflect.defineProperty(target, propertyKey, attributes)
const student = {}
Reflect.defineProperty(student, 'name', {
value: 'Mike'
}) // true
student.name // "Mike"
Reflect.deleteProperty 允许你删除一个对象上的属性。返回一个 Boolean 值表示该属性是否被成功删除。它几乎与非严格的 delete operator 相同。
Reflect.deleteProperty(target, propertyKey)
var obj = { x: 1, y: 2 } Reflect.deleteProperty(obj, "x") // true console.log(obj) // { y: 2 } key值 var arr = [1, 2, 3, 4, 5] Reflect.deleteProperty(arr, "3") // true console.log(arr) // [1, 2, 3, , 5] 索引值 // 如果属性不存在,返回 true console.log(Reflect.deleteProperty({}, "foo")) // true // 如果属性不可配置,返回 false let flag = Reflect.deleteProperty(Object.freeze({ foo: 1 }), "foo") // false console.log(flag)
Reflect.get() 方法的工作方式,就像从 object (target[propertyKey]) 中获取属性,但它是作为一个函数执行的。
Reflect.get(target, propertyKey[, receiver])
// Object var obj = { x: 1, y: 2 } Reflect.get(obj, 'x') // 1 // Array Reflect.get(['zero', 'one'], 1) // "one" // Proxy with a get handler var x = { p: 1 } var obj = new Proxy(x, { get(t, k, r) { return k + 'bar' } }) Reflect.get(obj, 'foo') // "foobar"
如果在对象中存在,则返回给定的属性的属性描述符,否则返回 undefined。
Reflect.getOwnPropertyDescriptor(target, propertyKey)
Reflect.getOwnPropertyDescriptor({
x: 'hello'
}, 'x')
// {value: "hello", writable: true, enumerable: true, configurable: true}
Reflect.getOwnPropertyDescriptor({
x: 'hello'
}, 'y')
// undefined
Reflect.getOwnPropertyDescriptor([], 'length')
// {value: 0, writable: true, enumerable: false, configurable: false}
返回指定对象的原型(即,内部的 [[Prototype]] 属性的值)。
Reflect.getPrototypeOf(target) // target 获取原型的目标对象
Reflect.has 用于检查一个对象是否拥有某个属性, 相当于in 操作符
Reflect.has(target, propertyKey)
Reflect.isExtensible 判断一个对象是否可扩展 (即是否能够添加新的属性)
Reflect.isExtensible(target) // target 获取原型的目标对象
Reflect.ownKeys 方法返回一个由目标对象自身的属性键组成的数组。它的返回值等同于 Object.getOwnPropertyNames(target).concat(Object.getOwnPropertySymbols(target))
Reflect.ownKeys(target) // target 获取原型的目标对象
Reflect.ownKeys({
z: 3,
y: 2,
x: 1
}) // [ "z", "y", "x" ]
Reflect.ownKeys([]) // ["length"]
Reflect.preventExtensions 方法阻止新属性添加到对象 例如:防止将来对对象的扩展被添加到对象中)。
Reflect.preventExtensions(target) // target 获取原型的目标对象
// Objects are extensible by default.
var empty = {}
Reflect.isExtensible(empty) // === true
// ...but that can be changed.
Reflect.preventExtensions(empty)
Reflect.isExtensible(empty) // === false
Reflect.set 方法允许你在对象上设置属性。它的作用是给属性赋值并且就像 property accessor 语法一样,但是它是以函数的方式。
Reflect.set(target, propertyKey, value[, receiver])
// Object var obj = {} Reflect.set(obj, "prop", "value") // true obj.prop // "value" // Array var arr = ["duck", "duck", "duck"] Reflect.set(arr, 2, "goose") // true arr[2] // "goose" // It can truncate an array. Reflect.set(arr, "length", 1) // true arr // ["duck"] // With just one argument, propertyKey and value are "undefined". var obj = {} Reflect.set(obj) // true Reflect.getOwnPropertyDescriptor(obj, "undefined") // { value: undefined, writable: true, enumerable: true, configurable: true }
Reflect.setPrototypeOf 方法改变指定对象的原型 (即,内部的 [[Prototype]] 属性值)
Reflect.setPrototypeOf(target, prototype)
Reflect.setPrototypeOf({}, Object.prototype) // true
// It can change an object's [[Prototype]] to null.
Reflect.setPrototypeOf({}, null) // true
// Returns false if target is not extensible.
Reflect.setPrototypeOf(Object.freeze({}), null) // false
// Returns false if it cause a prototype chain cycle.
var target = {}
var proto = Object.create(target)
Reflect.setPrototypeOf(target, proto) // false
( * & yield) yield加在想让他停下来的地方 ; function * 方法名{}
Generator 函数的定义不能使用箭头函数,否则会触发 SyntaxError 错误
function* generatorForLoop() {
for (let i = 0; i < 5; i += 1) {
yield console.log(i)
}
}
const genForLoop = generatorForLoop()
console.log(genForLoop.next()) // first console.log - 0
console.log(genForLoop.next()) // 1
console.log(genForLoop.next()) // 2
console.log(genForLoop.next()) // 3
console.log(genForLoop.next()) // 4
常规的循环只能一次遍历完所有值,Generator 可以通过调用 next 方法拿到依次遍历的值,让遍历的执行变得“可控”。
yield 关键字用来暂停和恢复一个生成器函数;yield 表达式的返回值是 undefined,但是遍历器对象的 next 方法可以修改这个默认值
yield 后面还可加 * ,yeild * 是委托给另一个遍历器对象或者可遍历对象
function * add(){
let sum;
sum = yield * [1,2,3];
}
let l = add();
l.next();
l.next();
Generator 对象通过 next 方法来获取每一次遍历的结果,这个方法返回一个对象,这个对象包含两个属性:value 和 done。value 是指当前程序的运行结果,done 表示遍历是否结束。
**其实 next 是可以接受参数的,**这个参数可以让你在 Generator 外部给内部传递数据,而这个参数就是作为 yield 的返回值。
function* gen() { var val = 100 while (true) { console.log( `before ${val}` ) val = yield val console.log( `return ${val}` ) } } var g = gen() console.log(g.next(20).value) // before 100 // 100 console.log(g.next(30).value) // return 30 // before 30 // 30 console.log(g.next(40).value) // return 40 // before 40 // 40
return 方法可以让 Generator 遍历终止,有点类似 for 循环的 break。
function* gen() {
yield 1
yield 2
yield 3
}
var g = gen()
console.log(g.next()) // {value: 1, done: false}
console.log(g.return(100)) // {value: 100, done: true}
console.log(g.next()) // {value: undefined, done: true}
可以通过 throw 方法在 Generator 外部控制内部执行的“终断”。
function* gen() { while (true) { try { yield 42 } catch (e) { console.log(e.message) } } } let g = gen() console.log(g.next()) // { value: 42, done: false } console.log(g.next()) // { value: 42, done: false } console.log(g.next()) // { value: 42, done: false } // 中断操作 g.throw(new Error('break')) console.log(g.next()) // {value: undefined, done: true}
如果想退出遍历 catch 之后可以配合 return false 使用,能起到 “break” 的作用
function* gen() { while (true) { try { yield 42 } catch (e) { console.log(e.message) } } } let g = gen() console.log(g.next()) // { value: 42, done: false } console.log(g.next()) // { value: 42, done: false } console.log(g.next()) // { value: 42, done: false } // 中断操作 g.throw(new Error('break')) console.log(g.next()) // {value: undefined, done: true}
let authors = { allAuthors: { fiction: ['Agatha Christie', 'J. K. Rowling', 'Dr. Seuss'], scienceFiction: ['Neal Stephenson', 'Arthur Clarke', 'Isaac Asimov', 'Robert Heinlein'], fantasy: ['J. R. R. Tolkien', 'J. K. Rowling', 'Terry Pratchett'] } } // 实现自定义遍历的接口 //先在对象上挂载一个名字是 Symbol.iterator 的属性,这个属性赋值一个方法,方法的输入是this,输出是return authors[Symbol.iterator] = function(){ return { next(){ return { done:false, //done 表示遍历是否结束,true:结束了,false:没结束 value:1, //当前遍历的值 } } } }
const name = 'hello' let addr = 'BeiJing City' var list = [1, 2, 3] export { //导入时需要写在{}中 name as cname, addr as caddr } export default list //导入时不需要写在{}中 //导入 import list,{cname.caddr} from './ts' or import list, * as mod from A console.log(list) console.log(mod.cname) console.log(mod.caddr)
const say = (content) => {
console.log(content)
}
let run = () => {
console.log('run')
}
export {
say,
run
}
class Test {
constructor() {
this.id = 2
}
}
export {
Test
}
如果想为输入的变量重新取一个名字,import命令要使用as关键字,将输入的变量重命名。
const name = 'hello'
let addr = 'BeiJing City'
var list = [1, 2, 3]
export {
name as cname, //cname为新名字
addr as caddr, //caddr为新名字
list
}
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。