前端小知识

187 阅读16分钟

作者: 打了激素的土猹

手写不易, 如要转发, 请备注作者/来源/出处 | 如有纰漏 请联系 乐意修改

Array数组

Array.map( )

map()方法 遍历 返回一个新数组, 每个元素都被调用一次提供的函数后的返回这组成

const arr = [1,2,3,4]
arr.map((it)=> it * 2); //[2,4,6,8]

Array.reduce( )

reduce()方法对数组中的 每个元素 执行累加,也就是累加器,每次一运行reducer回将先前计算的结果作为参数传入,最后将其结果汇总为单个返回值

const arr = [1,2,3,4]
arr.reduce((method,item)=> method + item, 0); //10

Array.reduceRight( )

reduceRight()方法和reduce()一样都是实现累加功能,但是reduceRight()是从数组的 末尾 向前做累加

const arr = [1,2,3,4]
arr.reduce((method,item)=> method + item, 0); //10

Array.push( )

push()方法是用来在数组的 末尾追加 一个元素,并返回该数组添加以后的长度

const arr = [1,2,3,4]
arr.push(5); 
console.log(arr); // [1,2,3,4,5]

Array.pop( )

pop()方法是用来 删除 数组末尾的最后一个元素,并返回该原素的值

const arr = [1, 2, 3, 4]
arr.pop();
console.log(arr); // [1, 2, 3]

Array.unshift( )

unshift()方法是在数组的 最前面 添加一个元素,返回该数组的新长度,会修改原数组

const arr = [1,2,3,4]
arr.unshift(5);
console.log(arr); // [5,1,2,3,4]

Array.shift( )

shift()方法是 删除 数组的中前面第一个元素,返回该元素的值,并修改原数组

const arr = [1,2,3,4]
arr.shift();
console.log(arr); // [2,3,4]

Array.splice( )

splice()方法截取数组中的某些内容,按照数组的索引来截取,返回截取元素,并修改原数组,第一个值是开始位置,第二个值是截取多少个,第三个值可以不写或者进行替换

const arr = [1,2,3,4]
arr.splice(1,2);
console.log(arr); // [1,4]

Array.reverse( )

reverse()方法可以将数组中元素的位置进行 反转 并返回该数组,改变原数组

const arr = [1,2,3,4]
arr.reverse();
console.log(arr); // [4,3,2,1]

Array.sort( )

sort()方法对数组中的元素进行 排序 并返回数组,通过将元素转换为字符串,然后比较它们的UTF-16代码单元值序列时构建的

const arr = [4,1,3,2,10]
arr.sort();  // [1,10,2,3,4]
arr.sort((a, b)= > a - b); // [1,2,3,4,10]

Array.concat( )

concat()方法可以 拼接 两个或多个数组,返回一个新数组,包含已连接数组的值

var arr = [1,2,3,4]
var array = [5,6,7,8]
var arrays = arr.concat(array)
console.log(arrays); // 1,2,3,4,5,6,7,8

Array.join( )

join()方法可以将一个数组的所有元素 连接 成一个字符串,并返回这个字符串

const arr = [1,2,3,4]
arr.join('~'); // "1~2~3~4"

Array.slice( )

slice()方法可以 复制 数组的一部分,返回一个新的数组对象,传入两个参数:slice(开始位置,结束位置),包含开始位置,不包含结束位置,不改变原数组,浅拷贝

const arr = [1,2,3,4]
arr.slice(1,2); // [2]

Array.find( )

find()方法返回数组中 满足 你提供的函数的第一个元素的值,每一个元素都调用一次函数执行,否则返回undefined

const arr = [1,2,3,4]
arr.find((item) => item === 2); // 2
arr.find((item) => item === 5); // undefined

Array.findIndex( )

findIndex()方法返回传入一个 测试函数 符合条件的数组 第一个 元素的索引,如果没有找到对应的元素则返回-1

const arr = [1,2,3,4]
arr.findIndex((item) => item > 2); // 2
arr.findIndex((item) => item > 5); // -1

Array.forEach( )

forEach()方法用于 遍历 数组中的每个元素,并将元素传递给回调函数,不能执行于空数组

const arr = [1,2,3,4]
arr.forEach(element => {
console.log(element); // 1,2,3,4
});

Array.filter( )

filter()方法可以进行 过滤 数组,返货满足所提供函数实现测试的所有元素

const arr = [1,2,3,4]
arr.filter((item) => item % 2 === 0); //[2,4]

Array.every( )

every()方法对数组中 每一项进行判断 返回布尔值,若都符合返回true,有一个不符合就会返回false 一假则假

const arr = [1,2,3,4]
arr.every((item) => item >= 2); // true
arr.every((item) => item > 2); // false

Array.some( )

some()方法和every差不多,对数组中每一项进行判断,如果有一个满足了提供的测试函数,就会返回true一真则真

const arr = [1,2,3,4]
arr.every((item) => item = 2); // true
arr.every((item) => item > 2); // false

Array.indexOf( )

indexOf()方法检测当前值在数组中第一次出现的 索引 找不到返回-1

const arr = [1,2,3,4]
arr.indexOf(3); // 2
arr.indexOf(5); // -1

Array.lastIndexOf( )

lastIndexOf()方法检测当前值在数组中 最后一次出现的索引 找不到返回-1 从数组后面开始检测

const arr = [1,2,3,4]
arr.indexOf(3); // 1

Array.includes( )

includes()方法用来判断一个数组 是否包含 一个指定的值或者字符串,如果包含返回true,否则返回false

const list = [1, 2, 3, 4];
list.includes(3); // true 
list.includes(5); // false

Array.at( )

at()方法就是一个 整数值 并返回该索引的item,允许正数和负数,负数从数组中的最后一位开始倒数

const arr = [1,2,3,4]
arr.ar(1); // 2
arr.ar(-1); // 4
arr.ar(-3); // 2

Array.from( )

from()方法对一个 数组 或者可迭代对象创建一个新的,浅拷贝的数组实例,搭配new Set()使用去重

const arr = 1234
Array.from(arr); // [1,2,3,4]

const arr = [1,1,2,2,3,3,4,4,5,5];
const setData = Array.from(new Set(arr));
console.log(setData); // [1,2,3,4,5]

Array.of( )

Array.of()方法它可以创建一个具有 可变数量参数 的新数组实例,不考虑参数的数量和类型

特别注意:Array.of()Array()区别在于整理函数,Array.of()创建的是一个具有单个元素的数组,而Array()创建的是一个对应长度的空数组,这个空不是undefined是指有多少个空位的数组

Array.of(8); // [8] 
Array.of(1, 2, 3,4); // [1, 2, 3,4] 

Array(8); // [ , , , , , , , ] 
Array(1, 2, 3,4); // [1, 2, 3,4]

Array.isArray( )

isArray()方法用来 判断 传递的值 是否 是一个数组,返回布尔值

Array.isArray([1, 2, 3, 4]); // true 
Array.isArray(2); // false

Array.flat( )

flat()方法可以 递归遍历 数组,并将所有元素与遍历元素合并为一个新的数组返回

var newArray = arr.flat([depth])
// depth可以指定要提权嵌套数组的结构深度,默认值为1,可以不写
const arr = [1,2,[3,4,[5,6,7]]]
arr.flat(Infinity); // [1,2,3,4,5,6,7]

Array.flatMap( )

flatMap()方法先用 映射 函数映射每一个元素,然后将结果压缩成一个新数组

const arr = [1,2,3,4]
arr.flatMap((item) => [item, item *item ]); //[1,1,2,4,3,9]

Object对象

Object.create( )

create()方法用于 创建 一个新对象,使用现有的对象来作为新创建对象的原型prototype

const obj = Object.create({ a : 1 }, { b : { value:2 }}) 
// 第一个参数为对象,对象为函数调用之后返回新对象的原型对象,第二个参数为对象本身的实例方法
obj.__proto__.a === 1 // true

Object.defineProperty( )

defineProperty()方法会直接在一个对象上 定义 一个新属性,或者修改一个对象的现有属性,并返回此对象

应当直接在 Object 构造器对象上调用此方法,而不是在任意一个 Object 类型的实例上调用

var obj = { }
Object.defineProperty( obj, "newDataProperty", { value:6 })
Object.defineProperty   // 6
// 修改数据属性
Object.defineProperty( obj, "newDataProperty", { value:9 })

Object.defineProperties( )

defineProperties()方法直接在一个对象上 定义 新的属性或 修改 现有属性,并返回该对象,本质上定义了对象上的可枚举属性相对应的所有属性

// 语法: Object.defineProperties(obj, props)
// obj=>在其上定义或修改属性的对象
// props=>要定义其可枚举属性或修改的属性描述符的对象
var obj = {};
Object.defineProperties(obj, {
  'property': {
    value: true,
    writable: true
  },
  'property1': {
    value: 'Hello',
    writable: false
  }
})

Object.keys( )

keys()方法会返回一个由一个给定对象的自身 可枚举属性 组成的数组,数组中属性名的排列顺序和正常循环遍历该对象时返回的顺序一致, 只包含对象本身可枚举属性,不包含原型链可枚举属性

const object1 = {
  a: 'somestring',
  b: 42,
  c: false
};
console.log(Object.keys(object1)); // ["a", "b", "c"]

Object.values( )

values()方法返回一个给定对象自身的所有可枚举属性 的数组,值的顺序与使用for...in循环的顺序相同(区别在于 for-in 循环枚举原型链中的属性)

// obj被返回可枚举属性值的对象
// 语法: Object.values(obj)

var obj = { foo: 'bar', baz: 42 };
console.log(Object.values(obj)); // ['bar', 42]

var obj = { 0: 'a', 1: 'b', 2: 'c' };
console.log(Object.values(obj)); // ['a', 'b', 'c']

var an_obj = { 100: 'a', 2: 'b', 7: 'c' };
console.log(Object.values(an_obj)); // ['b', 'c', 'a']

Object.assign( )

assign()方法用于对象的 合并 将所有可枚举(返回true)的自有(返回true)属性从一个或多个源对象复制到目标对象,返回修改后的对象

const target = { a: 1, b: 1 };
const source1 = { b: 2, c: 2 };
const source2 = { c: 3 };
Object.assign(target, source1, source2); target // {a:1, b:2, c:3}
// 浅拷贝

Object.getPrototypeOf( )

getPrototypeOf()方法返回指定对象的 原型(内部属性的值)

// 参数obj返回其原型的对象
// 返回值是给定对象的原型,如果没有继承属性,则返回null
const prototype1 = {};
const object1 = Object.create(prototype1);
console.log(Object.getPrototypeOf(object1) === prototype1); // true

Object.setPrototypeOf( )

setPrototypeOf()方法设置一个指定的对象的原型(即,内部 属性)到另一个对象或null,考虑到现代JavaScript 引擎优化属性访问所带来的特性的关系,建议使用Object.create()来创建对象

// 语法: Object.setPrototypeOf(obj, prototype)
// 参数: obj要设置其原型的对象 / prototype该对象的新原型(一个 对象 或 null )
const obj = {a: 1}, prototype = {b:2}
Object.setPrototypeOf(obj, prototype)
obj.__prototype__ === prototype     //true

Object.getOwnPropertyNames( )

getOwnPropertyNames()方法与keys相似,返回一个由指定对象的所有自身属性的属性名(包括不可枚举属性但不包括 Symbol 值作为名称的属性)组成的数组

// 语法: Object.getOwnPropertyNames(obj)
// 参数: 一个对象,其自身的可枚举和不可枚举属性的名称被返回
var arr = ["a", "b", "c"];
console.log(Object.getOwnPropertyNames(arr).sort()); // ["0", "1", "2", "length"]

// 类数组对象
var obj = { 0: "a", 1: "b", 2: "c"};
console.log(Object.getOwnPropertyNames(obj).sort()); // ["0", "1", "2"]


//不可枚举属性
var my_obj = Object.create({}, {
  getFoo: {
    value: function() { return this.foo; },
    enumerable: false
  }
});
my_obj.foo = 1;

console.log(Object.getOwnPropertyNames(my_obj).sort()); // ["foo", "getFoo"]

Object.getOwnPropertyDescriptor( )

getOwnPropertyDescriptor()方法返回 指定对象 上一个自有属性对应的属性描述符

// 语法: getOwnPropertyDescriptor( obj, prop)
// 参数: obj需要查找的目标对象 / prop目标对象内属性名称 
let obj = { prop: 123 };
Object.getOwnPropertyDescriptor(obj, 'prop')

Object.getOwnPropertyDescriptors( )

getOwnPropertyDescriptors( )方法用来获取一个对象的所有自身属性的描述对象

// 语法: getOwnPropertyDescriptors( obj )
// 参数: obj任意对象
const obj = {
foo: 123,
get bar() { return 'abc' }
};
console.dir(Object.getOwnPropertyDescriptors(obj))

使用场景 ↓

Object.assign()方法只能拷贝源对象的可枚举的自身属性,同时拷贝时无法拷贝属性的特性们,而且访问器属性会被转换成数据属性,也无法拷贝源对象的原型,该方法配合Object.create()方法可以实现

Object.create(
  Object.getPrototypeOf(obj),
  Object.getOwnPropertyDescriptors(obj)
);

Object.entries( )

entries()方法用来分割对象其元素是与直接在上找到的可枚举属性键值对相对应的数组。属性的顺序与通过手动循环对象的属性值所给出的顺序相同

// 语法:Object.entries(obj)
// 参数: obj可以返回其可枚举属性的键值对的对象

const obj = { foo: 'bar', baz: 42 };
console.log(Object.entries(obj)); // [ ['foo', 'bar'], ['baz', 42] ]

const obj = { 0: 'a', 1: 'b', 2: 'c' };
console.log(Object.entries(obj)); // [ ['0', 'a'], ['1', 'b'], ['2', 'c'] ]

Object.is( )

is()方法判断两个值是否为同一个值是否严格相等与===行为一致

// 语法: Object.is(value1, value2);
// 参数: value1被比较的第一个值, value2被比较的第二个值
Object.is(25, 25);                // true
Object.is('foo', 'foo');          // true
Object.is('foo', 'bar');          // false
Object.is(null, null);            // true
Object.is(undefined, undefined);  // true
Object.is(window, window);        // true
Object.is([], []);                // false
var foo = { a: 1 };
var bar = { a: 1 };
Object.is(foo, foo);              // true
Object.is(foo, bar);              // false

Object.preventExtensions( )

preventExtensions()方法让一个对象变的不可扩展,也就是永远不能再添加新的属性

&isExtensible() 判断一个对象是否可扩展

// 语法: Object.preventExtensions( obj )
// 参数: obj将要变的不可扩展的对象

// Object.preventExtensions 将原对象变的不可扩展,并且返回原对象。
var obj = {};
var obj2 = Object.preventExtensions(obj);
obj === obj2;  // true

// 字面量方式定义的对象默认是可扩展的。
var empty = {};
Object.isExtensible(empty) //=== true

// ...但可以改变。
Object.preventExtensions(empty);
Object.isExtensible(empty) //=== false

Object.seal( )

seal()方法封闭一个对象,阻止添加新属性并将所有现有属性标记为不可配置。当前属性的值只要原来是可写的就可以改变

isSealed 判断一个对象是否为密封的

// 语法: Object.seal( obj )
// 参数: obj将要被密封的对象

Object.freeze( )

freeze()方法可以冻结一个对象, 一个被冻结的对象再也不能被修改

isFrozen 判断一个对象是否已经被冻结

// 语法: Object.freeze( obj )
// 参数: obj将要被冻结的对象

var obj = {
  prop: function() {},
  foo: 'bar'
};

// 新的属性会被添加,已存在的属性可能
// 会被修改或移除
obj.foo = 'baz';
obj.lumpy = 'woof';
delete obj.prop;

// 作为参数传递的对象与返回的对象都被冻结
// 所以不必保存返回的对象(因为两个对象全等)
var o = Object.freeze(obj);

o === obj; // true
Object.isFrozen(obj); // === true

// 现在任何改变都会失效
obj.foo = 'quux'; // 静默地不做任何事
// 静默地不添加此属性
obj.quaxxor = 'the friendly duck';

// 在严格模式,如此行为将抛出 TypeErrors
function fail(){
  'use strict';
  obj.foo = 'sparky'; // throws a TypeError
  delete obj.quaxxor; // 返回 true,因为 quaxxor 属性从来未被添加
  obj.sparky = 'arf'; // throws a TypeError
}

fail();

// 试图通过 Object.defineProperty 更改属性
// 下面两个语句都会抛出 TypeError.
Object.defineProperty(obj, 'ohai', { value: 17 });
Object.defineProperty(obj, 'foo', { value: 'eit' });

// 也不能更改原型
// 下面两个语句都会抛出 TypeError.
Object.setPrototypeOf(obj, { x: 20 })
obj.__proto__ = { x: 20 }

Object.hasOwn( )

hasOwn()如果指定的对象 自身 有指定的属性,则静态方法Object.hasOwn()返回true 如果属性是继承的或者不存在,该方法返回false

const object1 = {
  prop: 'exists'
};
console.log(Object.hasOwn(object1, 'prop'));
// true
console.log(Object.hasOwn(object1, 'toString'));
// false
console.log(Object.hasOwn(object1, 'undeclaredPropertyValue'));
// false

Object.prototype.hasOwnProperty( )

hasOwnProperty()方法会返回一个布尔值,指示对象自身属性中是否具有指定的属性(也就是,是否有指定的键)

// 语法: obj.hasOwnProperty(prop)
// 参数: prop要检测的属性的 String字符串形式表示的名称,或者Symbol
const object1 = {};
object1.property1 = 42;

console.log(object1.hasOwnProperty('property1'));
// true

console.log(object1.hasOwnProperty('toString'));
// false

console.log(object1.hasOwnProperty('hasOwnProperty'));
// false

即使属性值的nullundefined,只要属性存在,hasOwnProperty依旧返回true
o = new Object();
o.propOne = null;
o.hasOwnProperty('propOne'); // 返回 true
o.propTwo = undefined;
o.hasOwnProperty('propTwo'); // 返回 true

Object.prototype.isPrototypeOf( )

isPrototypeOf()方法用于测试一个对象是否存在于另一个对象的原型链上,返回布尔值

// 语法: prototypeObj.isPrototypeOf(object)
// 参数: object在该对象的原型链上搜寻
function Foo() {}
function Bar() {}
function Baz() {}

Bar.prototype = Object.create(Foo.prototype);
Baz.prototype = Object.create(Bar.prototype);

var baz = new Baz();

console.log(Baz.prototype.isPrototypeOf(baz)); // true
console.log(Bar.prototype.isPrototypeOf(baz)); // true
console.log(Foo.prototype.isPrototypeOf(baz)); // true
console.log(Object.prototype.isPrototypeOf(baz)); // true

Object.prototype.propertyIsEnumerable( )

propertyIsEnumerable()方法返回一个布尔值,表示指定的属性是否可枚举

// 语法: obj.propertyIsEnumerable(prop)
// 参数: prop需要测试的属性名

var o = {};
var a = [];
o.prop = 'is enumerable';
a[0] = 'is enumerable';

o.propertyIsEnumerable('prop'); // 返回 true
a.propertyIsEnumerable(0);      // 返回 true

// 用户自定义对象和内置对象
var a = ['is enumerable'];

a.propertyIsEnumerable(0);        // 返回 true
a.propertyIsEnumerable('length'); // 返回 false

Math.propertyIsEnumerable('random'); // 返回 false
this.propertyIsEnumerable('Math');   // 返回 false

Object.getOwnPropertySymbols( )

getOwnPropertySymbols()方法返回一个给定对象自身的所有 Symbol 属性的数组

// 语法: Object.getOwnPropertySymbols(obj)
// 参数: obj要返回 Symbol 属性的对象
var obj = {};
var a = Symbol("a");
var b = Symbol.for("b");

obj[a] = "localSymbol";
obj[b] = "globalSymbol";

var objectSymbols = Object.getOwnPropertySymbols(obj);

console.log(objectSymbols.length); // 2
console.log(objectSymbols)         // [Symbol(a), Symbol(b)]
console.log(objectSymbols[0])      // Symbol(a)

Object.prototype.valueOf( )

valueOf()方法返回指定对象的原始值

// 在自定义类型中使用
function MyNumberType(n) {
  this.number = n;
}

MyNumberType.prototype.valueOf = function () {
  return this.number;
};

const myObj = new MyNumberType(4);
myObj + 3; // 7

Object.prototype.toString( )

toString()方法返回一个表示该对象的字符串

toLocaleString一样

// 语法: obj.toString()
var o = new Object();
o.toString(); // 返回 [object Object]

// 与toLocaleString的区别
// 如果是个时间对象
(new Date).toString(); //"Mon Nov 06 2017 13:02:46 GMT+0800 (China Standard Time)"
(new Date).toLocaleString();  //"2022/11/7 下午1:03:12"
// 如果是个时间戳时,toLocaleString会把时间戳每三位添加一个逗号 , 
(Date.parse(new Date())).toLocaleString() // "1,667,791,894,000"
(Date.parse(new Date())).toString() // "1667791894000"

Object.prototype.toLocaleString( )

toLocaleString()方法返回一个该对象的字符串表示

toString一样

// 与toString的区别
// 如果是个时间对象
(new Date).toString(); //"Mon Nov 06 2017 13:02:46 GMT+0800 (China Standard Time)"
(new Date).toLocaleString();  //"2022/11/7 下午1:03:12"
// 如果是个时间戳时,toLocaleString会把时间戳每三位添加一个逗号 , 
(Date.parse(new Date())).toLocaleString() // "1,667,791,894,000"
(Date.parse(new Date())).toString() // "1667791894000"

Object.fromEntries( )

fromEntries()方法把键值对列 表转换 为一个对象

const map = new Map([ ['foo', 'bar'], ['baz', 42] ]);
const obj = Object.fromEntries(map);
console.log(obj); // { foo: "bar", baz: 42 }

Object.isExtensible( )

isExtensible()方法判断一个对象 是否是可扩展 的(是否可以在它上面添加新的属性)

// 语法: Object.isExtensible(obj)
// 参数: obj需要检测的对象
// 新对象默认是可扩展的。
var empty = {};
Object.isExtensible(empty); // === true

// ...可以变的不可扩展。
Object.preventExtensions(empty);
Object.isExtensible(empty); // === false

// 密封对象是不可扩展的。
var sealed = Object.seal({});
Object.isExtensible(sealed); // === false

// 冻结对象也是不可扩展。
var frozen = Object.freeze({});
Object.isExtensible(frozen); // === false

Object.isFrozen( )

isFrozen()方法判断一个对象是否被冻结

// 语法: Object.isFrozen(obj)
// 参数: obj被检测的对象
// 一个对象默认是可扩展的,所以它也是非冻结的。
Object.isFrozen({}); // === false

// 一个不可扩展的空对象同时也是一个冻结对象。
var vacuouslyFrozen = Object.preventExtensions({});
Object.isFrozen(vacuouslyFrozen) //=== true;

// 一个非空对象默认也是非冻结的。
var oneProp = { p: 42 };
Object.isFrozen(oneProp) //=== false

// 让这个对象变的不可扩展,并不意味着这个对象变成了冻结对象,
// 因为 p 属性仍然是可以配置的 (而且可写的).
Object.preventExtensions(oneProp);
Object.isFrozen(oneProp) //=== false

// 此时,如果删除了这个属性,则它会成为一个冻结对象。
delete oneProp.p;
Object.isFrozen(oneProp) //=== true

// 一个不可扩展的对象,拥有一个不可写但可配置的属性,则它仍然是非冻结的。
var nonWritable = { e: "plep" };
Object.preventExtensions(nonWritable);
Object.defineProperty(nonWritable, "e", { writable: false }); // 变得不可写
Object.isFrozen(nonWritable) //=== false

// 把这个属性改为不可配置,会让这个对象成为冻结对象。
Object.defineProperty(nonWritable, "e", { configurable: false }); // 变得不可配置
Object.isFrozen(nonWritable) //=== true

// 一个不可扩展的对象,拥有一个不可配置但可写的属性,则它仍然是非冻结的。
var nonConfigurable = { release: "the kraken!" };
Object.preventExtensions(nonConfigurable);
Object.defineProperty(nonConfigurable, "release", { configurable: false });
Object.isFrozen(nonConfigurable) //=== false

// 把这个属性改为不可写,会让这个对象成为冻结对象。
Object.defineProperty(nonConfigurable, "release", { writable: false });
Object.isFrozen(nonConfigurable) //=== true

// 一个不可扩展的对象,值拥有一个访问器属性,则它仍然是非冻结的。
var accessor = { get food() { return "yum"; } };
Object.preventExtensions(accessor);
Object.isFrozen(accessor) //=== false

// ...但把这个属性改为不可配置,会让这个对象成为冻结对象。
Object.defineProperty(accessor, "food", { configurable: false });
Object.isFrozen(accessor) //=== true

// 使用 Object.freeze 是冻结一个对象最方便的方法。
var frozen = { 1: 81 };
Object.isFrozen(frozen) //=== false
Object.freeze(frozen);
Object.isFrozen(frozen) //=== true

// 一个冻结对象也是一个密封对象。
Object.isSealed(frozen) //=== true

// 当然,更是一个不可扩展的对象。
Object.isExtensible(frozen) //=== false

Object.isSealed( )

isSealed()方法判断一个对象是否被密封

// 语法: Object.isSealed(obj)
// 参数: obj要被检查的对象

// 新建的对象默认不是密封的
var empty = {};
Object.isSealed(empty); // === false

// 如果你把一个空对象变的不可扩展,则它同时也会变成个密封对象。
Object.preventExtensions(empty);
Object.isSealed(empty); // === true

// 但如果这个对象不是空对象,则它不会变成密封对象,因为密封对象的所有自身属性必须是不可配置的。
var hasProp = { fee: "fie foe fum" };
Object.preventExtensions(hasProp);
Object.isSealed(hasProp); // === false

// 如果把这个属性变的不可配置,则这个属性也就成了密封对象。
Object.defineProperty(hasProp, 'fee', {
  configurable: false
});
Object.isSealed(hasProp); // === true

// 最简单的方法来生成一个密封对象,当然是使用 Object.seal.
var sealed = {};
Object.seal(sealed);
Object.isSealed(sealed); // === true

// 一个密封对象同时也是不可扩展的。
Object.isExtensible(sealed); // === false

// 一个密封对象也可以是一个冻结对象,但不是必须的。
Object.isFrozen(sealed); // === true,所有的属性都是不可写的
var s2 = Object.seal({ p: 3 });
Object.isFrozen(s2); // === false,属性"p"可写

var s3 = Object.seal({ get p() { return 0; } });
Object.isFrozen(s3); // === true,访问器属性不考虑可写不可写,只考虑是否可配置

原文