ES6

ES5

严格规范模式

由于js的作用域和隐式声明变量等语法会造成很多预想不到的错误,所以ES5中新增了一个严格模式的语法,用于严格规范代码的书写。

"use strict";

要放在代码的最前面,也就是在script标签中的第一行或者某个函数中的第一行,否则会失效
严格模式可以规范当前script标签或者当前函数中的代码,不能规范别的script标签中的代码和别的函数

不允许隐式声明变量
禁止函数中的形参重名
禁止函数中的this代表window



JSON

json是一种特殊的字符串格式,本质是一个字符串

  var jsonObj = '{ "name": "Jack", "age": 18, "gender": "男" }'
  var jsonArr = '[{ "name": "Jack", "age": 18, "gender": "男" },
  { "name": "Jack", "age": 18, "gender": "男" }, 
  { "name": "Jack", "age": 18, "gender": "男" }]'

就是对象内部的 keyvalue 都用双引号包裹的字符串(必须是双引号)


JSON方法

1.JSON.parse

JSON.parse 是将 json 格式的字符串转换为 js 的对象或者数组

可以将数字字符串转成数字

  var jsonObj = '{ "name": "Jack", "age": 18, "gender": "男" }'
  var jsonArr = '[{ "name": "Jack", "age": 18, "gender": "男" }, 
  { "name": "Jack", "age": 18, "gender": "男" },
   { "name": "Jack", "age": 18, "gender": "男" }]'
  
  var obj = JSON.parse(jsonStr)
  var arr = JSON.parse(jsonArr)
  
  console.log(obj)  //js 的对象
  console.log(arr)  //js 的数组

2.JSON.stringify

json.stringify 是将 js 的对象或者数组转换成为 json 格式的字符串

  var obj = {
    name: 'Jack',
    age: 18,
    gender: '男'
  }
  var arr = [
    {
      name: 'Jack',
      age: 18,
      gender: '男'
    },
    {
      name: 'Jack',
      age: 18,
      gender: '男'
    },
    {
      name: 'Jack',
      age: 18,
      gender: '男'
    }
  ]
  
  var jsonObj = JSON.stringify(obj)
  var jsonArr = JSON.stringify(arr)
  
  console.log(jsonObj)  //json 格式的对象字符串
  console.log(jsonArr)  //json 格式的数组字符串

  JSON.stringify(obj,['name']) 
  // 可以接收第二个参数 第二个参数为一个数组 包括需要筛选出来的值
  // 只会将筛选出来的值转成Json字符串



ES6


Symbol

ES6新的原始数据类型Symbol,表示独一无二的值,Symbol不能与其他数据运算

symbol定义的对象属性不能使用for…in循环遍历,但是可以使用Reflect.ownKeys获取对象所有键名

let s = Symbol()
let s2 = Symbol(`ss`) 
let s3 = Symbol.for(`sss`) 

Symbol.for()

创建以参数作为描述的Symbol值,如存在此参数则返回原有的Symbol值(先搜索后创建,登记在全局环境)

Symbol.keyFor()

返回已登记的Symbol值的描述(只能返回Symbol.for()的key)

Object.getOwnPropertySymbols()

返回对象中所有用作属性名的Symbol值的数组


迭代器

迭代器(iterator)是一种接口,为各种不同的数据结构提供统一的访问机制,任何数据结构只要部署Iterator接口,就可以完成遍历操作(即依次处理该数据结构的所有成员)。

一是为各种数据结构,提供一个统一的、简便的访问接口

使得数据结构的成员能够按某种次序排列

ES6创造了一种新的遍历命令for…of循环,Iterator接口主要供for…of消费

for-in遍历顺序:不同的引擎已就如何迭代属性达成一致,从而使行为标准化 ES11

原生具备iterator接口的数据(Array、Arguments、Set、Map、String、TypedArray、Nodelist)

工作原理

创建一个指针对象,指向当前数据结构的起始位置
第一次调用对象的next()方法,指针自动指向数据结构的第一个成员
接下来不断调用next()方法,指针一直向后移动,直到指向最后一个成员

 // 基本使用
 let arr = ["hello", "world"];
 let map = arr[Symbol.iterator]();
 console.log(map.next()); // {value: 'hello', done: false}
 console.log(map.next()); // {value: 'world', done: false}
 console.log(map.next()); // {value: undefined, done: true}
 
 // for of 循环
 let arr = ["hello", "world"];
 for (let value of arr) {
    console.log(value); // hello world
 }
 
 // 对象处理
 let obj = {
     start: [1, 5, 2],
     end: [7, 9, 6],
     [Symbol.iterator](){
         let index = 0;
         let arr = this.start.concat(this.end)
         return {
             next(){
                 if(index < arr.length){
                     return {
                         value: arr[index++],
                         done: false
                     }
                 }else{
                     return {
                         value: arr[index++],
                         done: true
                     }
                 }
             }
         }
     }
 }
 for (let key of obj) {
    console.log(key); // 1 5 2 7 9 6
 }

Generator

是可以用来控制迭代器的函数,也是封装多个内部状态的异步编程解决方案,也叫生成器函数

Generator 函数的定义不能使用箭头函数,否则会触发 SyntaxError 错误

yield

yield 来控制程序内部的执行的 “暂停”,并返回一个对象,这个对象包括两个属性:value 和 done
其中 value 代表值, done返回布尔(如果为false,代表后续还有,为true则已完成)

next
next 来恢复程序执行

let data = function* (){
     yield "a";
     yield "b";
     return "c"
 }
 
 let generator = data();
 console.log(generator.next()) //{value: 'a', done: false} 
 console.log(generator.next()) //{value: 'b', done: false} 
 console.log(generator.next()) //{value: 'c', done: true} 
 console.log(generator.next()) //{value: undefined, done: true}

Decorator 装饰器

使用@符号,用来扩展,修改类的行为
使用的时候需要引入第三方库 如: core-decorators

const name = (target) => {
     target.name = "domesy"
 }
 
 @name
 class Test{}
 
 console.log(Test.name) //domesy



1.变量

let 定义变量

const 定义常量(特殊的变量)


var let const的区别

var 会进行预解析 let/const不会进行预解析

var 可以声明两个重名的变量 let/const不能定义重名变量

var 没有块级作用域 let/const有块级作用域
块级作用域:任何一个可以执行代码段的{ } 都会限制该变量的适用范围

let定义变量时可以不进行赋值,const在定义时必须赋值

let定义的变量可以被修改,const定义的常量一经赋值不能被修改

注: let与const依然会变量提升,但在声明之前都不能使用,这个提升->声明的无法使用这个变量的 区域 称为暂时死区

补充:
其实,let和const是会被提升的,准确的说是创建被提升了,但是初始化没有被提升。

根据ECMA-262中13.3.1的NOTE中所述:let and const declarations define variables that are scoped to the running execution context’s LexicalEnvironment. The variables are created when their containing Lexical Environment is instantiated but may not be accessed in any way until the variable’s LexicalBinding is evaluated. A variable defined by a LexicalBinding with an Initializer is assigned the value of its Initializer’s AssignmentExpression when the LexicalBinding is evaluated, not when the variable is created. If a LexicalBinding in a let declaration does not have an Initializer the variable is assigned the value undefined when the LexicalBinding is evaluated.

这段话的大概意思就是let和const定义了变量执行的词法环境,变量会在这个环境实例化时被创建,但是在变量的词法绑定之前不允许以任何方式对其进行访问…如果let声明的变量初始化时没有词法绑定,则分配一个未定义的值undefined,同时MDN上关于let介绍中也说到 var 和 let 的不同之处在于后者是在编译时才初始化。(词法环境应该是指上下文环境,而词法绑定应该就是赋值操作。)

也就说可以这么理解,let声明变量分为三部分:1.创建,2.初始化,3.赋值。
创建环节在当前环境实例化时完成。而通过const命令声明的是一个常量,一旦声明,常量的值(内存地址不能改变)就不能改变 ,所以const声明必须立即进行初始化,不能留到以后赋值,所以const声明变量分为两部分:1.创建,2.初始化,没有赋值操作,相当于把初始化赋值整合成了一步,在初始化的时候进行赋值。



2.箭头函数

是ES6的语法中对函数表达式的简写,对声明式函数不能使用,只能用于匿名函数


箭头函数的特殊之处

当形参只有一个的时候,可以不写( )

当你的代码只有一句话的时候,可以不写{ }
并且会自动把这一句话的结果当做函数的返回值

箭头函数内没有arguments

箭头函数内没有this,箭头函数内的this就是外部作用域的this


3.形参默认值

定义函数的形参时可以设置默认值,当调用函数没有对应数量的实参时则使用默认值

function fn(a=100){
	console.log(a)
}
fn()  //==>100
fn(200)  //==>200

注意: 箭头函数如果你需要使用默认值的话,那么一个参数的时候也需要写 ()


4.解构

1.解构数组

快速从数组中获取数据

let[a,b]=['hello','world']
console.log(a)  //==>'hello'
console.log(b)  //==>'world'

//表示定义两个变量 a,b分别接受数组中的索引为0,1的两个数据

多重解构

var arr=[a,b,[c,[d]]];
var [_,_,[_,[x]]]=arr; //_代表没用但必须要有的变量(必须要var,相当于重复定义_覆盖赋值)
let [,,[,[y]]]=arr;    //相当于跳过不想解构的元素

2.解构对象

快速从对象中获取数据

//原来
let name =obj.name

//现在
let obj={ name:'jack' ,age:18}
let{name}=obj

//表示定义一个叫做name的变量,获取的是obj内一个叫做name的成员的值
//不能定义其他名字 因为只能解构出数组内同名成员 但可以起一个别名

var{age:a}=obj
//相当于定义一个a变量,从obj内获取一个叫做age的值

如果取了别名,跟键相同的变量名就不能用了(name变量名是例外 是关键字,随时可以用)

3.解构字符串

字符串也能进行解构,还能从中解构出length属性

 let [a, b, c, d, e] = "hello"
 console.log(a, b, c, d, e) // h e l l o
 
 let { length } = "hello"
 console.log(length) // 5

4.解构数字,布尔值

解构的只要不为对象或数组,都会先将其转化为对象,所以数字类型和布尔类型也换转化为对象

 let { toString: s } = 123;
 console.log(s === Number.prototype.toString) // true
 
 let { toString: s } = true;
 console.log(s === Boolean.prototype.toString) // true

5.函数解构参数

 let arr = [[1,2], [3, 4]]
 let res = arr.map([a, b] => a + b)
 console.log(res) // [3, 7]
 
 let arr = [1, undefined, 2]
 let res = arr.map((a = 'test') => a);
 console.log(res) // [1, 'test', 2]
 
 let func = ({x, y} = {x: 0, y: 0}) => {
    return [x, y]
 }
 console.log(func(1, 2)) // [undefined, undefined]
 console.log(func()) // [0, 0]
 console.log(func({})) // [undefined, undefined]
 console.log(func({x: 1})) // [1, undefined]
 
 
 let func = ({x=0, y=0}) => {
    return [x, y]
 }
 
 console.log(func({x:1,y:2})) // [1, 2]
 console.log(func()) // error
 console.log(func({})) // [0, 0]
 console.log(func({x: 1})) // [1, 0]

多重解构

var {wife:{sex,age}}=obj

解构时在起别名的位置继续解构



5.字符串

可以换行书写,会解析空格换行

可以直接在字符串内解析变量 ${ 变量 }



6.展开运算符…

用于展开对象及数组

1.合并数组

2.给函数传递参数

3.用于复制对象,但需注意书写顺序,当有相同成员时存在覆盖问题



7.类Class

对一类具有共同特征的事物的抽象(构造函数语法糖)

class 类名 {
	constructor(){} //构造函数体
	
	//原型方法直接书写
	
	static //定义静态属性与方法需要与static关键字连用
}
//必须和new关键字连用,不连用会直接报错
//调用与构造函数相同

extends 继承

 class Parent {
     constructor(name = 'es6'){
         this.name = name
     }
 }
 
 // 普通继承
 class Child extends Parent {}
 console.log(new Child()) //  Child { name: 'es6'} 
 
 // 传递参数
 class Child extends Parent {
    constructor(name = "child") {
        super(name);
        this.type = "child";
    }
 }
 console.log(new Child('domesy')) //  Child { name: 'domesy', type: 'child'}

getter setter

这个两个方法比较重要,常常用来封装API
get 和 set 是属性,而不是方法

class Parent {
     constructor(name = 'es6'){
         this.name = name
     }
     // getter
     get getName() {
         return 'sy' + this.name
     } 
     // setter
     set setName(value){
         this.name = value
     }
 }
 
 let data = new Parent()
 console.log(data.getName) // syes6
 
 data.setName = 'domesy'
 console.log(data.getName) // domesy

static 静态

// static 静态方法

静态方法,不能在类的实例上调用静态方法,而应该通过类本身调用

 class Parent {
     static getName = (name) => {
         return `你好!${name}`
     }
 }
 
 console.log(Parent.getName('domesy')) // 你好!domesy

// 静态属性
 class Parent {}
 Parent.type = "test";
 
 console.log(Parent.type); //test



8.立即执行函数


立即执行函数是在函数被声明或者定义后马上执行,其思路就是在函数体后面直接添加括号,如果需要传递参数则直接写在这个括号里面。

(function(x){console.log(x)}(1))

这种方式不支持箭头函数

(function(x){console.log(x)})(1)

这种方式支持箭头函数,即

((x)=>{console.log(x)})(1)

 !function(x){console.log(x)}(1)

在function前面加!、+、 -或者使用void操作符等到都可以起到函数定义后立即执行的效果,而()、!、+、-、=等运算符,都将函数声明转换成函数表达式。

:这个方式不支持使用箭头函数!,此外,使用!来构成的话,这个整体会返回true,用±来构成的话整体返回NaN



9.set数据结构


set数据结构类似数组,但是成员值唯一,没有重复值

set本身是一个构造函数,用来生成set数据结构

const s = new Set();

set函数可以接收一个数组作为变量,用来初始化

const s = new Set([1,2,3,4,4]);

set实例方法

add(value) 添加某个值,返回set结构本身

delete(value) 删除某个值,返回一个布尔值,表示是否删除成功

has(value) 返回一个布尔值,表示该值是否为set成员

clear() 清除所有成员,没有返回值

const s = new Set();

s.size  //获取该数据类型中的数据个数

s.add(1).add(2).add(3);  //向set结构添加值

s.delete(2)				//删除set结构中的2值

s.has(1)				//表示set结构中是否有1这个值,返回布尔值

s.clear()				//清除set结构中的所有值

s.keys() //用于输出集合中所有的键

s.values() //用于输出集合中所有的值

s.entries() //用于输出集合中所有的键值对(条目)

注:set同样有forEach方法

WeakSet

和Set的结构,但成员值只能为对象

const set = new WeakSet()

add()   //在WeakSet对象尾部添加一个元素。返回该实例

delete()  //移除WeakSet的中与这个值相等的元素

has()  //是否存在这个值,如果存在为 true,否则为false

注意:

WeakSet 成员的对象都是弱引用,即垃圾回收机制不考虑该对象的应用。简单地说WebSet 的对象无法遍历
好处是,再删除实例的时候,不会出现内存泄露



10.map数据结构


map是一个数据集合,类似于对象 ,在对象中存储key一定是字符串类型,map里key可以为任何数据类型(值=值的数据类型)

map本身是一个构造函数,用来生成map对象

const m = new Map();

方法

map.size  //获取该数据类型中的数据个数

map.constructor //构造函数,返回Map

map.get()  //获取该数据集合中的某一个数据

map.set("键","值") //新增/修改key-value

map.has("键") //用于判断集合中是否存在一个数据

map.keys() //用于输出集合中所有的键

map.values() //用于输出集合中所有的值

map.entries() //用于输出集合中所有的键值对(条目)

map.delete("键","值") //删除key-value

map.clear() //清除所有key-value

WeakMap

和Map的结构,但成员值只能为对象

const set = new WeakMap()

set()   //添加键值对,返回实例

get()   //返回键值对

delete()   //删除键值对,如果存在为 true,否则为false

has()  //是否存在这个值,如果存在为 true,否则为false



Proxy

Proxy用于修改某些操作的默认行为,等同于在语言层面做出修改,所以属于一种“元编程”(meta programming),即对编程语言进行编程
Proxy就是在目标对象之前设置的一层拦截,外界想要访问都要经过这层拦截,因此提供了一种机制,可以对外界的访问进行过滤和改写。
Proxy 在这里可以理解为代理器

const proxy = new Proxy(target, handler)

// target: 拦截的对象
// handler: 定义拦截的方法


get()  //拦截对象属性的读取
set()  //拦截对象设置属性,返回一个布尔值
has()  //拦截 propKey in proxy 的操作,返回一个布尔值
ownKeys()  //拦截对象属性遍历,返回一个数组
deleteProperty()  //拦截 delete proxy[propKey] 的操作,返回一个布尔值()
apply()  //拦截函数的调用,call 和 apply 操作
construct()  //拦截 new 命令,返回一个对象: 拦截 new 命令,返回一个对象



Reflect

Reflect 与 Proxy 类似,只是保持Object的默认行为

将 Object 对象的一些明显属于语言内部的方法(比如 Object.defineProperty),放到 Reflect 对象上。

现阶段,某些方法同时在 Object 和 Reflect 对象上部署,未来的新方法将只部署在 Reflect 对象上

修改某些 Object 方法的返回结果,让其变得更合理。
比如,Object.defineProperty(obj, name, desc)在无法定义属性时,会抛出一个错误,而 Reflect.defineProperty(obj, name, desc)则会返回 false

⽐如 name in obj 和 delete obj[name] ,Reflect让它们变成了函数⾏为 Reflect.has(obj, name) 和Reflect.deleteProperty(obj, name)

Reflect.apply(target, thisArg, args)
Reflect.construct(target, args)
Reflect.get(target, name, receiver)
Reflect.set(target, name, value, receiver)
Reflect.defineProperty(target, name, desc)
Reflect.deleteProperty(target, name)
Reflect.has(target, name)
Reflect.ownKeys(target)
Reflect.isExtensible(target)
Reflect.preventExtensions(target)
Reflect.getOwnPropertyDescriptor(target, name)
Reflect.getPrototypeOf(target)
Reflect.setPrototypeOf(target, prototype)

上面这些方法的作用,大部分与 Object 对象的同名方法的作用都是相同的,而且它与 Proxy 对象的方法是一 一对应的。

1、Reflect.get(target, name, receiver)

Reflect.get 方法查找并返回 target 对象的 name 属性,如果没有该属性,则返回 undefined。

let obj = {
  name: 'webchang',
  age: 18,
  get info() {
    return this.name + ' ' + this.age;
  }
}
console.log(Reflect.get(obj, 'name')); // webchang
console.log(Reflect.get(obj, 'age'));  // 18
console.log(Reflect.get(obj, 'info')); // webchang 18

如果 Reflect.get(target, name, receiver) 的第二个参数属性部署了读取函数(getter):

没有第三个参数,this 绑定当前对象
有第三个参数,读取函数的 this 绑定到第三个参数 receiver 上。

let obj = {
  name: 'webchang',
  age: 18,
  get info() {
    return this.name + ' ' + this.age;
  }
}

let obj2 = {
  name: '张三',
  age: 40
}

console.log(Reflect.get(obj, 'info', obj2));// 张三 40

target 对象也可以是数组:

Reflect.get([1,2,3], 1) // 输出索引 1 对应的值:2
1
如果第一个参数不是对象,Reflect.get 方法会报错。

Reflect.get(1, 'foo') // 报错 TypeError: Reflect.get called on non-object
Reflect.get(false, 'foo') // 报错 
1
2
2、Reflect.set(target, name, value, receiver)
Reflect.set 方法设置 target 对象的 name 属性等于 value。

let obj = {
  name: 'webchang',
  set age(value) {
    this._age = value;
  }
}
console.log(obj.name); // webchang
Reflect.set(obj, 'name', '李四'); 
console.log(obj.name); // 李四

Reflect.set(obj, 'age', 18);
console.log(obj._age); // 18

3、Reflect.has(obj, name)
Reflect.has 方法对应 name in obj 里面的 in 运算符。如果 Reflect.has() 方法的第一个参数不是对象,会报错。

var myObject = {
  foo: 1,
};

// 旧写法
'foo' in myObject // true

// 新写法
Reflect.has(myObject, 'foo') // true

4、Reflect.deleteProperty(obj, name)

Reflect.deleteProperty 方法等同于 delete obj[name],用于删除对象的属性。该方法返回一个布尔值。如果删除成功,或者被删除的属性不存在,返回true;删除失败,被删除的属性依然存在,返回false。

如果 Reflect.deleteProperty() 方法的第一个参数不是对象,会报错。

const myObj = { foo: 'bar' };

// 旧写法
delete myObj.foo;

// 新写法
Reflect.deleteProperty(myObj, 'foo');

5、Reflect.construct(target, args)

Reflect.construct 方法等同于 new target(…args) ,这提供了一种不使用 new,来调用构造函数的方法。第一个参数是函数,第二个参数是数组。

function Person(name, age) {
  this.name = name;
  this.age = age;
}

// new 的写法
let p1 = new Person('webchang', 18);

// Reflect.construct 的写法,两种写法最终效果一样
let p2 = Reflect.construct(Person, ['webchang', 18]);

6、Reflect.getPrototypeOf(obj)

Reflect.getPrototypeOf 方法用于读取对象的 proto 属性,对应 Object.getPrototypeOf(obj)。

function Person() {}
let p = new Person();

console.log(Object.getPrototypeOf(p) === Person.prototype); // true
console.log(Reflect.getPrototypeOf(p) === Person.prototype);// true

如果参数不是对象,Object.getPrototypeOf 会将这个参数转为对象,然后再运行,而Reflect.getPrototypeOf 会报错。

Object.getPrototypeOf(1); // Number {[[PrimitiveValue]]: 0}
Reflect.getPrototypeOf(1); // TypeError: Reflect.getPrototypeOf called on non-object

7、Reflect.setPrototypeOf(obj, newProto)

Reflect.setPrototypeOf 方法用于设置目标对象的原型(prototype),对应 Object.setPrototypeOf(obj, newProto) 方法。它返回一个布尔值,表示是否设置成功。

let obj = {
  name: 'webchang'
}

// 旧写法,设置成功会返回修改后的对象
Object.setPrototypeOf(obj, Array.prototype);

// 新写法,设置成功会返回 true
Reflect.setPrototypeOf(obj, Array.prototype);

如果第一个参数不是对象,Object.setPrototypeOf 会返回第一个参数本身,而 Reflect.setPrototypeOf 会报错。

Object.setPrototypeOf(1, {})
// 1

Reflect.setPrototypeOf(1, {})
// TypeError: Reflect.setPrototypeOf called on non-object

如果第一个参数是 undefined 或 null ,Object.setPrototypeOf 和 Reflect.setPrototypeOf 都会报错。

Object.setPrototypeOf(null, {})
// TypeError: Object.setPrototypeOf called on null or undefined

Reflect.setPrototypeOf(null, {})
// TypeError: Reflect.setPrototypeOf called on non-object

8、Reflect.apply(func, thisArg, args)

第一个参数是函数,第二个参数用来指定 this 的指向,第三个参数是数组。

一般来说,如果要绑定一个函数的 this 对象,可以这样写 fn.apply(obj, args),但是如果函数定义了自己的 apply 方法,就只能写成 Function.prototype.apply.call(fn, obj, args) ,采用 Reflect 对象可以简化这种操作。

const ages = [11, 33, 12, 54, 18, 96];

// 旧写法
const youngest = Math.min.apply(Math, ages);
const oldest = Math.max.apply(Math, ages);

// 新写法
const youngest = Reflect.apply(Math.min, Math, ages);
const oldest = Reflect.apply(Math.max, Math, ages);

9、Reflect.defineProperty(target, propertyKey, attributes)

Reflect.defineProperty 方法基本等同于 Object.defineProperty,用来为对象定义属性。

function MyDate() {
  /*…*/
}

// 旧写法
Object.defineProperty(MyDate, 'now', {
  value: () => Date.now()
});

// 新写法
Reflect.defineProperty(MyDate, 'now', {
  value: () => Date.now()
});

10、Reflect.getOwnPropertyDescriptor(target, propertyKey)

let obj = {
  name: 'webchang'
}
console.log(Object.getOwnPropertyDescriptor(obj, 'name'));
console.log(Reflect.getOwnPropertyDescriptor(obj, 'name'));

如果第一个参数不是对象,Object.getOwnPropertyDescriptor(1, ‘foo’) 不报错,返回 undefined,而Reflect.getOwnPropertyDescriptor(1, ‘foo’) 会抛出错误,表示参数非法。

11、Reflect.isExtensible (target)

Reflect.isExtensible 方法对应 Object.isExtensible,返回一个布尔值,表示当前对象是否可扩展。

let obj = {}

// 旧写法
Object.isExtensible(obj); // true

// 新写法
Reflect.isExtensible(obj); // true

Object.freeze(obj);
Reflect.isExtensible(obj); // false

如果参数不是对象,Object.isExtensible 会返回 false,因为非对象本来就是不可扩展的,而 Reflect.isExtensible 会报错。

Object.isExtensible(1) // false
Reflect.isExtensible(1) // TypeError: Reflect.isExtensible called on non-object

12、Reflect.preventExtensions(target)

Reflect.preventExtensions 对应 Object.preventExtensions 方法,用于让一个对象变为不可扩展。它返回一个布尔值,表示是否操作成功。

var myObject = {};

// 旧写法
Object.preventExtensions(myObject) // Object {}

// 新写法
Reflect.preventExtensions(myObject) // true

如果参数不是对象,Object.preventExtensions 在 ES5 环境报错,在 ES6 环境返回传入的参数,而Reflect.preventExtensions会报错。

// ES5 环境
Object.preventExtensions(1) // 报错

// ES6 环境
Object.preventExtensions(1) // 1

// 新写法
Reflect.preventExtensions(1) // 报错

13、Reflect.ownKeys (target)

Reflect.ownKeys 方法用于返回对象的所有属性,基本等同于 Object.getOwnPropertyNames 与Object.getOwnPropertySymbols 之和。如果 Reflect.ownKeys() 方法的第一个参数不是对象,会报错。

var myObject = {
  foo: 1,
  bar: 2,
  [Symbol.for('baz')]: 3,
  [Symbol.for('bing')]: 4,
};

// 旧写法
Object.getOwnPropertyNames(myObject)
// ['foo', 'bar']

Object.getOwnPropertySymbols(myObject)
//[Symbol(baz), Symbol(bing)]

// 新写法
Reflect.ownKeys(myObject)
// ['foo', 'bar', Symbol(baz), Symbol(bing)]

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Raccom

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值