• JavaScript系列之内置对象Object


    文章の目录


    一、静态方法

    1、Object.assign()

    1.1、概述

    Object.assign() 方法将所有可枚举(Object.propertyIsEnumerable() 返回 true)的自有(Object.hasOwnProperty() 返回 true)属性从一个或多个源对象复制到目标对象,返回修改后的对象。

    1.2、语法

    Object.assign(target, ...sources)
    
    • 1

    1.3、参数

    • target
      目标对象,接收源对象属性的对象,也是修改后的返回值。

    • sources
      源对象,包含将被合并的属性。

    1.4、返回值

    目标对象。

    1.5、描述

    如果目标对象与源对象具有相同的 key,则目标对象中的属性将被源对象中的属性覆盖,后面的源对象的属性将类似地覆盖前面的源对象的属性。

    Object.assign 方法只会拷贝源对象 可枚举的自身的 属性到目标对象。该方法使用源对象的 [[Get]] 和目标对象的 [[Set]],它会调用 getters 和 setters。故它分配属性,而不仅仅是复制或定义新的属性。如果合并源包含 getters,这可能使其不适合将新属性合并到原型中。

    为了将属性定义(包括其可枚举性)复制到原型,应使用 Object.getOwnPropertyDescriptor()Object.defineProperty(),基本类型 String 和 Symbol 的属性会被复制。

    如果赋值期间出错,例如如果属性不可写,则会抛出 TypeError;如果在抛出异常之前添加了任何属性,则会修改 target 对象(译者注:换句话说,Object.assign() 没有“回滚”之前赋值的概念,它是一个尽力而为、可能只会完成部分复制的方法)。

    1.6、示例

    const obj = { a: 1 };
    const copy = Object.assign({}, obj);
    console.log(copy); // { a: 1 }
    
    • 1
    • 2
    • 3

    2、Object.create()

    2.1、概述

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

    2.2、语法

    Object.create(proto)
    Object.create(proto, propertiesObject)
    
    • 1
    • 2

    2.3、参数

    • proto
      新创建对象的原型对象

    • propertiesObject【可选】
      如果该参数被指定且不为 undefined,则该传入对象的自有可枚举属性(即其自身定义的属性,而不是其原型链上的枚举属性)将为新创建的对象添加指定的属性值和对应的属性描述符。这些属性对应于 Object.defineProperties() 的第二个参数。

    2.4、返回值

    一个新对象,带着指定的原型对象及其属性。

    2.5、异常

    proto 参数需为

    • null 或
    • 除基本类型包装对象以外的对象

    如果 proto 不是这几类值,则抛出一个 TypeError 异常。

    2.6、示例

    // Shape - superclass
    function Shape() {
    	this.x = 0;
    	this.y = 0;
    }
    
    // superclass method
    Shape.prototype.move = function (x, y) {
    	this.x += x;
    	this.y += y;
    	console.info("Shape moved.");
    };
    
    // Rectangle - subclass
    function Rectangle() {
    	Shape.call(this); // call super constructor.
    }
    
    // subclass extends superclass
    Rectangle.prototype = Object.create(Shape.prototype);
    
    //If you don't set Rectangle.prototype.constructor to Rectangle,
    //it will take the prototype.constructor of Shape (parent).
    //To avoid that, we set the prototype.constructor to Rectangle (child).
    Rectangle.prototype.constructor = Rectangle;
    
    const rect = new Rectangle();
    
    console.log("Is rect an instance of Rectangle?", rect instanceof Rectangle); // true
    console.log("Is rect an instance of Shape?", rect instanceof Shape); // true
    rect.move(1, 1); // Outputs, 'Shape moved.'
    
    • 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

    3、Object.defineProperties()

    3.1、概述

    Object.defineProperties() 方法直接在一个对象上定义新的属性或修改现有属性,并返回该对象。

    3.2、语法

    Object.defineProperties(obj, props)
    
    • 1

    3.3、参数

    • obj
      在其上定义或修改属性的对象。

    • props
      要定义其可枚举属性或修改的属性描述符的对象。对象中存在的属性描述符主要有两种:数据描述符和访问器描述符。描述符具有以下键:

    configurable
    true 只有该属性描述符的类型可以被改变并且该属性可以从对应对象中删除。 默认为 false

    enumerable
    true 只有在枚举相应对象上的属性时该属性显现。 默认为 false

    value
    与属性关联的值。可以是任何有效的 JavaScript 值(数字,对象,函数等)。 默认为 undefined.

    writable
    true只有与该属性相关联的值被assignment operator 改变时。 默认为 false

    get
    作为该属性的 getter 函数,如果没有 getter 则为undefined。函数返回值将被用作属性的值。 默认为 undefined

    set
    作为属性的 setter 函数,如果没有 setter 则为undefined。函数将仅接受参数赋值给该属性的新值。 默认为 undefined

    3.4、返回值

    传递给函数的对象。

    3.5、描述

    Object.defineProperties 本质上定义了 obj 对象上 props 的可枚举属性相对应的所有属性。

    3.6、示例

    var obj = {};
    Object.defineProperties(obj, {
    	property1: {
    		value: true,
    		writable: true
    	},
    	property2: {
    		value: "Hello",
    		writable: false
    	}
    	// etc. etc.
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    3.7、兼容性

    function defineProperties(obj, properties) {
    	function convertToDescriptor(desc) {
    		function hasProperty(obj, prop) {
    			return Object.prototype.hasOwnProperty.call(obj, prop);
    		}
    
    		function isCallable(v) {
    			// NB: modify as necessary if other values than functions are callable.
    			return typeof v === "function";
    		}
    
    		if (typeof desc !== "object" || desc === null) throw new TypeError("bad desc");
    
    		var d = {};
    
    		if (hasProperty(desc, "enumerable")) d.enumerable = !!desc.enumerable;
    		if (hasProperty(desc, "configurable")) d.configurable = !!desc.configurable;
    		if (hasProperty(desc, "value")) d.value = desc.value;
    		if (hasProperty(desc, "writable")) d.writable = !!desc.writable;
    		if (hasProperty(desc, "get")) {
    			var g = desc.get;
    
    			if (!isCallable(g) && typeof g !== "undefined") throw new TypeError("bad get");
    			d.get = g;
    		}
    		if (hasProperty(desc, "set")) {
    			var s = desc.set;
    			if (!isCallable(s) && typeof s !== "undefined") throw new TypeError("bad set");
    			d.set = s;
    		}
    
    		if (("get" in d || "set" in d) && ("value" in d || "writable" in d)) throw new TypeError("identity-confused descriptor");
    
    		return d;
    	}
    
    	if (typeof obj !== "object" || obj === null) throw new TypeError("bad obj");
    
    	properties = Object(properties);
    
    	var keys = Object.keys(properties);
    	var descs = [];
    
    	for (var i = 0; i < keys.length; i++) descs.push([keys[i], convertToDescriptor(properties[keys[i]])]);
    
    	for (var i = 0; i < descs.length; i++) Object.defineProperty(obj, descs[i][0], descs[i][1]);
    
    	return obj;
    }
    
    • 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

    4、Object.defineProperty()

    4.1、概述

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

    4.2、语法

    Object.defineProperty(obj, prop, descriptor)
    
    • 1

    4.3、参数

    • obj
      要定义属性的对象。

    • prop
      要定义或修改的属性的名称或 Symbol 。

    • descriptor
      要定义或修改的属性描述符。

    4.4、返回值

    被传递给函数的对象。

    4.5、示例

    var o = {}; // 创建一个新对象
    
    // 在对象中添加一个属性与数据描述符的示例
    Object.defineProperty(o, "a", {
    	value: 37,
    	writable: true,
    	enumerable: true,
    	configurable: true
    });
    
    // 对象 o 拥有了属性 a,值为 37
    
    // 在对象中添加一个设置了存取描述符属性的示例
    var bValue = 38;
    Object.defineProperty(o, "b", {
    	// 使用了方法名称缩写(ES2015 特性)
    	// 下面两个缩写等价于:
    	// get : function() { return bValue; },
    	// set : function(newValue) { bValue = newValue; },
    	get() {
    		return bValue;
    	},
    	set(newValue) {
    		bValue = newValue;
    	},
    	enumerable: true,
    	configurable: true
    });
    
    o.b; // 38
    // 对象 o 拥有了属性 b,值为 38
    // 现在,除非重新定义 o.b,o.b 的值总是与 bValue 相同
    
    // 数据描述符和存取描述符不能混合使用
    Object.defineProperty(o, "conflict", {
    	value: 0x9f91102,
    	get() {
    		return 0xdeadbeef;
    	}
    });
    // 抛出错误 TypeError: value appears only in data descriptors, get appears only in accessor descriptors
    
    • 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

    5、Object.entries()

    5.1、概述

    **Object.entries()**方法返回一个给定对象自身可枚举属性的键值对数组,其排列与使用 for…in 循环遍历该对象时返回的顺序一致(区别在于 for-in 循环还会枚举原型链中的属性)。

    5.2、语法

    Object.entries(obj)
    
    • 1

    5.3、参数

    • obj
      可以返回其可枚举属性的键值对的对象。

    5.4、返回值

    给定对象自身可枚举属性的键值对数组。

    5.5、示例

    const obj = { foo: "bar", baz: 42 };
    console.log(Object.entries(obj)); // [ ['foo', 'bar'], ['baz', 42] ]
    
    // array like object
    const obj = { 0: "a", 1: "b", 2: "c" };
    console.log(Object.entries(obj)); // [ ['0', 'a'], ['1', 'b'], ['2', 'c'] ]
    
    // array like object with random key ordering
    const anObj = { 100: "a", 2: "b", 7: "c" };
    console.log(Object.entries(anObj)); // [ ['2', 'b'], ['7', 'c'], ['100', 'a'] ]
    
    // getFoo is property which isn't enumerable
    const myObj = Object.create(
    	{},
    	{
    		getFoo: {
    			value() {
    				return this.foo;
    			}
    		}
    	}
    );
    myObj.foo = "bar";
    console.log(Object.entries(myObj)); // [ ['foo', 'bar'] ]
    
    // non-object argument will be coerced to an object
    console.log(Object.entries("foo")); // [ ['0', 'f'], ['1', 'o'], ['2', 'o'] ]
    
    // iterate through key-value gracefully
    const obj = { a: 5, b: 7, c: 9 };
    for (const [key, value] of Object.entries(obj)) {
    	console.log(`${key} ${value}`); // "a 5", "b 7", "c 9"
    }
    
    // Or, using array extras
    Object.entries(obj).forEach(([key, value]) => {
    	console.log(`${key} ${value}`); // "a 5", "b 7", "c 9"
    });
    
    • 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

    5.6、兼容性

    if (!Object.entries)
    	Object.entries = function (obj) {
    		var ownProps = Object.keys(obj),
    			i = ownProps.length,
    			resArray = new Array(i); // preallocate the Array
    		while (i--) resArray[i] = [ownProps[i], obj[ownProps[i]]];
    
    		return resArray;
    	};
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    6、Object.freeze()

    6.1、概述

    Object.freeze() 方法可以冻结一个对象。一个被冻结的对象再也不能被修改;冻结了一个对象则不能向这个对象添加新的属性,不能删除已有属性,不能修改该对象已有属性的可枚举性、可配置性、可写性,以及不能修改已有属性的值。此外,冻结一个对象后该对象的原型也不能被修改。freeze() 返回和传入的参数相同的对象。

    6.2、语法

    Object.freeze(obj)
    
    • 1

    6.3、参数

    • obj
      要被冻结的对象。

    6.4、返回值

    被冻结的对象。

    6.5、示例

    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 };
    
    • 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

    7、Object.fromEntries()

    7.1、概述

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

    7.2、语法

    Object.fromEntries(iterable);
    
    • 1

    7.3、参数

    • iterable
      类似 Array 、 Map 或者其它实现了可迭代协议的可迭代对象。

    7.4、返回值

    一个由该迭代对象条目提供对应属性的新对象。

    7.5、示例

    const map = new Map([
    	["foo", "bar"],
    	["baz", 42]
    ]);
    const obj = Object.fromEntries(map);
    console.log(obj); // { foo: "bar", baz: 42 }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    8、Object.getOwnPropertyDescriptor()

    8.1、概述

    Object.getOwnPropertyDescriptor() 方法返回指定对象上一个自有属性对应的属性描述符。(自有属性指的是直接赋予该对象的属性,不需要从原型链上进行查找的属性)

    8.2、语法

    Object.getOwnPropertyDescriptor(obj, prop)
    
    • 1

    8.3、参数

    • obj
      需要查找的目标对象

    • prop
      目标对象内属性名称

    8.4、返回值

    如果指定的属性存在于对象上,则返回其属性描述符对象(property descriptor),否则返回 undefined。

    8.5、描述

    该方法允许对一个属性的描述进行检索。在 Javascript 中, 属性 由一个字符串类型的“名字”(name)和一个“属性描述符”(property descriptor)对象构成。更多关于属性描述符类型以及他们属性的信息可以查看:Object.defineProperty。

    一个属性描述符是一个记录,由下面属性当中的某些组成的:

    • value
      该属性的值 (仅针对数据属性描述符有效)

    • writable
      当且仅当属性的值可以被改变时为 true。(仅针对数据属性描述有效)

    • get
      获取该属性的访问器函数(getter)。如果没有访问器,该值为 undefined。(仅针对包含访问器或设置器的属性描述有效)

    • set
      获取该属性的设置器函数(setter)。如果没有设置器,该值为 undefined。(仅针对包含访问器或设置器的属性描述有效)

    • configurable
      当且仅当指定对象的属性描述可以被改变或者属性可被删除时,为 true。

    • enumerable
      当且仅当指定对象的属性可以被枚举出时,为 true。

    8.6、示例

    var o, d;
    
    o = {
    	get foo() {
    		return 17;
    	}
    };
    d = Object.getOwnPropertyDescriptor(o, "foo");
    // d {
    //   configurable: true,
    //   enumerable: true,
    //   get: /*the getter function*/,
    //   set: undefined
    // }
    
    o = { bar: 42 };
    d = Object.getOwnPropertyDescriptor(o, "bar");
    // d {
    //   configurable: true,
    //   enumerable: true,
    //   value: 42,
    //   writable: true
    // }
    
    o = {};
    Object.defineProperty(o, "baz", {
    	value: 8675309,
    	writable: false,
    	enumerable: false
    });
    d = Object.getOwnPropertyDescriptor(o, "baz");
    // d {
    //   value: 8675309,
    //   writable: false,
    //   enumerable: false,
    //   configurable: false
    // }
    
    • 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

    9、Object.getOwnPropertyDescriptors()

    9.1、概述

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

    9.2、语法

    Object.getOwnPropertyDescriptors(obj)
    
    • 1

    9.3、参数

    • obj
      任意对象

    9.4、返回值

    所指定对象的所有自身属性的描述符,如果没有任何自身属性,则返回空对象。

    9.5、示例

    创建子类的典型方法是定义子类,将其原型设置为超类的实例,然后在该实例上定义属性。这么写很不优雅,特别是对于 getters 和 setter 而言。 相反,您可以使用此代码设置原型:

    function superclass() {}
    superclass.prototype = {
    	// 在这里定义方法和属性
    };
    function subclass() {}
    subclass.prototype = Object.create(
    	superclass.prototype,
    	Object.getOwnPropertyDescriptors({
    		// 在这里定义方法和属性
    	})
    );
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    10、Object.getOwnPropertyNames()

    10.1、概述

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

    10.2、语法

    Object.getOwnPropertyNames(obj)
    
    • 1

    10.3、参数

    • obj
      一个对象,其自身的可枚举和不可枚举属性的名称被返回。

    10.4、返回值

    在给定对象上找到的自身属性对应的字符串数组。

    10.5、示例

    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"]
    
    // 使用 Array.forEach 输出属性名和属性值
    Object.getOwnPropertyNames(obj).forEach(function (val, idx, array) {
    	console.log(val + " -> " + obj[val]);
    });
    // 输出
    // 0 -> a
    // 1 -> b
    // 2 -> c
    
    //不可枚举属性
    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"]
    
    • 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

    11、Object.getOwnPropertySymbols()

    11.1、概述

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

    11.2、语法

    Object.getOwnPropertySymbols(obj)
    
    • 1

    11.3、参数

    • obj
      要返回 Symbol 属性的对象。

    11.4、返回值

    在给定对象自身上找到的所有 Symbol 属性的数组。

    11.5、示例

    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)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    12、Object.getPrototypeOf()

    12.1、概述

    Object.getPrototypeOf() 方法返回指定对象的原型(内部[[Prototype]]属性的值)。

    12.2、语法

    Object.getPrototypeOf(object)
    
    • 1

    12.3、参数

    • obj
      要返回其原型的对象。

    12.4、返回值

    给定对象的原型。如果没有继承属性,则返回 null 。

    12.5、示例

    var proto = {};
    var obj = Object.create(proto);
    Object.getPrototypeOf(obj) === proto; // true
    
    var reg = /a/;
    Object.getPrototypeOf(reg) === RegExp.prototype; // true
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    13、Object.hasOwn()

    13.1、概述

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

    13.2、语法

    hasOwn(instance, prop)
    
    • 1

    13.3、参数

    • instance
      JavaScript对象实例测试。

    • prop
      属性的字符串名称或Symbol进行测试。

    13.4、返回值

    如果指定的对象将指定的属性作为自己的属性,则返回true。否则该方法返回false。

    13.5、示例

    const example = {};
    Object.hasOwn(example, "prop"); // false - 'prop' has not been defined
    
    example.prop = "exists";
    Object.hasOwn(example, "prop"); // true - 'prop' has been defined
    
    example.prop = null;
    Object.hasOwn(example, "prop"); // true - own property exists with value of null
    
    example.prop = undefined;
    Object.hasOwn(example, "prop"); // true - own property exists with value of undefined
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    14、Object.is()

    14.1、概述

    Object.is() 方法判断两个值是否为同一个值。

    14.2、语法

    Object.is(value1, value2);
    
    • 1

    14.3、参数

    • value1
      被比较的第一个值。

    • value2
      被比较的第二个值。

    14.4、返回值

    一个布尔值,表示两个参数是否是同一个值。

    14.5、示例

    // Case 1: Evaluation result is the same as using ===
    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
    
    // Case 2: Signed zero
    Object.is(0, -0); // false
    Object.is(+0, -0); // false
    Object.is(-0, -0); // true
    Object.is(0n, -0n); // true
    
    // Case 3: NaN
    Object.is(NaN, 0 / 0); // true
    Object.is(NaN, Number.NaN); // true
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    14.6、兼容性

    if (!Object.is) {
    	Object.defineProperty(Object, "is", {
    		value: function (x, y) {
    			// SameValue algorithm
    			if (x === y) {
    				// return true if x and y are not 0, OR
    				// if x and y are both 0 of the same sign.
    				// This checks for cases 1 and 2 above.
    				return x !== 0 || 1 / x === 1 / y;
    			} else {
    				// return true if both x AND y evaluate to NaN.
    				// The only possibility for a variable to not be strictly equal to itself
    				// is when that variable evaluates to NaN (example: Number.NaN, 0/0, NaN).
    				// This checks for case 3.
    				return x !== x && y !== y;
    			}
    		}
    	});
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    15、Object.isExtensible()

    15.1、概述

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

    15.2、语法

    Object.isExtensible(obj)
    
    • 1

    15.3、参数

    • obj
      需要检测的对象

    15.4、返回值

    表示给定对象是否可扩展的一个 Boolean。

    15.5、示例

    // 新对象默认是可扩展的。
    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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    16、Object.isFrozen()

    16.1、概述

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

    16.2、语法

    Object.isFrozen(obj)
    
    • 1

    16.3、参数

    • obj
      被检测的对象。

    16.4、返回值

    表示给定对象是否被冻结的Boolean。

    16.5、示例

    // 一个对象默认是可扩展的,所以它也是非冻结的。
    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
    
    • 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

    17、Object.isSealed()

    17.1、概述

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

    17.2、语法

    Object.isSealed(obj)
    
    • 1

    17.3、参数

    • obj
      要被检查的对象。

    17.4、返回值

    表示给定对象是否被密封的一个Boolean 。

    17.5、示例

    // 新建的对象默认不是密封的。
    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 ,访问器属性不考虑可写不可写,只考虑是否可配置
    
    • 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

    18、Object.keys()

    18.1、概述

    Object.keys() 方法会返回一个由一个给定对象的自身可枚举属性组成的数组,数组中属性名的排列顺序和正常循环遍历该对象时返回的顺序一致。

    18.2、语法

    Object.keys(obj)
    
    • 1

    18.3、参数

    • obj
      要返回其枚举自身属性的对象。

    18.4、返回值

    一个表示给定对象的所有可枚举属性的字符串数组。

    18.5、示例

    // 简单数组
    const arr = ["a", "b", "c"];
    console.log(Object.keys(arr)); // console: ['0', '1', '2']
    
    // 类数组对象
    const obj = { 0: "a", 1: "b", 2: "c" };
    console.log(Object.keys(obj)); // console: ['0', '1', '2']
    
    // 具有随机键顺序的类数组对象
    const anObj = { 100: "a", 2: "b", 7: "c" };
    console.log(Object.keys(anObj)); // console: ['2', '7', '100']
    
    // getFoo 是一个不可枚举的属性
    const myObj = Object.create(
    	{},
    	{
    		getFoo: {
    			value() {
    				return this.foo;
    			}
    		}
    	}
    );
    myObj.foo = 1;
    console.log(Object.keys(myObj)); // console: ['foo']
    
    • 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

    19、Object.preventExtensions()

    19.1、概述

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

    19.2、语法

    Object.preventExtensions(obj)
    
    • 1

    19.3、参数

    • obj
      将要变得不可扩展的对象。

    19.4、返回值

    已经不可扩展的对象。

    19.5、示例

    // 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.defineProperty 方法为一个不可扩展的对象添加新属性会抛出异常。
    var nonExtensible = { removable: true };
    Object.preventExtensions(nonExtensible);
    Object.defineProperty(nonExtensible, "new", { value: 8675309 }); // 抛出 TypeError 异常
    
    // 在严格模式中,为一个不可扩展对象的新属性赋值会抛出 TypeError 异常。
    function fail() {
    	"use strict";
    	nonExtensible.newProperty = "FAIL"; // throws a TypeError
    }
    fail();
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    20、Object.seal()

    20.1、概述

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

    20.2、语法

    Object.seal(obj)
    
    • 1

    20.3、参数

    • obj
      将要被密封的对象。

    20.4、返回值

    被密封的对象。

    20.5、示例

    var obj = {
    	prop: function () {},
    	foo: "bar"
    };
    
    // 可以添加新的属性
    // 可以更改或删除现有的属性
    obj.foo = "baz";
    obj.lumpy = "woof";
    delete obj.prop;
    
    var o = Object.seal(obj);
    
    o === obj; // true
    Object.isSealed(obj); // === true
    
    // 仍然可以修改密封对象的属性值
    obj.foo = "quux";
    
    // 但是你不能将属性重新定义成为访问器属性
    // 反之亦然
    Object.defineProperty(obj, "foo", {
    	get: function () {
    		return "g";
    	}
    }); // throws a TypeError
    
    // 除了属性值以外的任何变化,都会失败。
    obj.quaxxor = "the friendly duck";
    // 添加属性将会失败
    delete obj.foo;
    // 删除属性将会失败
    
    // 在严格模式下,这样的尝试将会抛出错误
    function fail() {
    	"use strict";
    	delete obj.foo; // throws a TypeError
    	obj.sparky = "arf"; // throws a TypeError
    }
    fail();
    
    // 通过 Object.defineProperty 添加属性将会报错
    Object.defineProperty(obj, "ohai", {
    	value: 17
    }); // throws a TypeError
    Object.defineProperty(obj, "foo", {
    	value: "eit"
    }); // 通过 Object.defineProperty 修改属性值
    
    • 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

    21、Object.setPrototypeOf()

    21.1、概述

    Object.setPrototypeOf() 方法设置一个指定的对象的原型(即,内部 [[Prototype]] 属性)到另一个对象或 null。

    21.2、语法

    Object.setPrototypeOf(obj, prototype)
    
    • 1

    21.3、参数

    • obj
      要设置其原型的对象。

    • prototype
      该对象的新原型(一个对象或 null)。

    21.4、返回值

    指定的对象。

    21.5、异常

    • TypeError
      如果发生以下情况中的任何一个,则抛出该异常:

    • obj 参数是不可扩展的,或者它是一个不可修改原型的特异对象(exotic object),例如 Object.prototype 或 window。

    • prototype 参数不是对象或 null。

    21.6、示例

    class Human {}
    class SuperHero extends Human {}
    
    const superMan = new SuperHero();
    
    • 1
    • 2
    • 3
    • 4

    22、Object.values()

    22.1、概述

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

    22.2、语法

    Object.values(obj)
    
    • 1

    22.3、参数

    • obj
      被返回可枚举属性值的对象。

    22.4、返回值

    一个包含对象自身的所有可枚举属性值的数组。

    22.5、示例

    var obj = { foo: "bar", baz: 42 };
    console.log(Object.values(obj)); // ['bar', 42]
    
    // array like object
    var obj = { 0: "a", 1: "b", 2: "c" };
    console.log(Object.values(obj)); // ['a', 'b', 'c']
    
    // array like object with random key ordering
    // when we use numeric keys, the value returned in a numerical order according to the keys
    var an_obj = { 100: "a", 2: "b", 7: "c" };
    console.log(Object.values(an_obj)); // ['b', 'c', 'a']
    
    // getFoo is property which isn't enumerable
    var my_obj = Object.create(
    	{},
    	{
    		getFoo: {
    			value: function () {
    				return this.foo;
    			}
    		}
    	}
    );
    my_obj.foo = "bar";
    console.log(Object.values(my_obj)); // ['bar']
    
    // non-object argument will be coerced to an object
    console.log(Object.values("foo")); // ['f', 'o', 'o']
    
    • 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

    二、实例方法

    1、hasOwnProperty()

    1.1、概述

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

    1.2、语法

    obj.hasOwnProperty(prop)
    
    • 1

    1.3、参数

    • prop
      要检测的属性的 String 字符串形式表示的名称,或者 Symbol。

    1.4、返回值

    用来判断某个对象是否含有指定的属性的布尔值 Boolean。

    1.5、示例

    下面的例子演示了 hasOwnProperty 方法对待自身属性和继承属性的区别:

    o = new Object();
    o.prop = "exists";
    o.hasOwnProperty("prop"); // 返回 true
    o.hasOwnProperty("toString"); // 返回 false
    o.hasOwnProperty("hasOwnProperty"); // 返回 false
    
    • 1
    • 2
    • 3
    • 4
    • 5

    2、isPrototypeOf()

    2.1、概述

    isPrototypeOf() 方法用于测试一个对象是否存在于另一个对象的原型链上。

    2.2、语法

    prototypeObj.isPrototypeOf(object)
    
    • 1

    2.3、参数

    • object
      在该对象的原型链上搜寻

    2.4、返回值

    Boolean,表示调用对象是否在另一个对象的原型链上。

    2.5、报错

    • TypeError
      如果 prototypeObj 为 undefined 或 null,会抛出 TypeError。

    2.6、描述

    isPrototypeOf() 方法允许你检查一个对象是否存在于另一个对象的原型链上。

    2.7、示例

    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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    3、propertyIsEnumerable()

    3.1、概述

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

    3.2、语法

    obj.propertyIsEnumerable(prop)
    
    • 1

    3.3、参数

    • prop
      需要测试的属性名。

    3.4、返回值

    用来表示指定的属性名是否可枚举的布尔值。

    3.5、示例

    var o = {};
    var a = [];
    o.prop = "is enumerable";
    a[0] = "is enumerable";
    
    o.propertyIsEnumerable("prop"); // 返回 true
    a.propertyIsEnumerable(0); // 返回 true
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    4、toLocaleString()

    4.1、概述

    toLocaleString() 方法返回一个该对象的字符串表示。此方法被用于派生对象为了特定语言环境的目的(locale-specific purposes)而重载使用。

    4.2、语法

    obj.toLocaleString();
    
    • 1

    4.3、返回值

    表示对象的字符串。

    5、toString()

    5.1、概述

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

    5.2、语法

    obj.toString()
    
    • 1

    5.3、返回值

    一个表示该对象的字符串。

    5.4、示例

    function Dog(name, breed, color, sex) {
    	this.name = name;
    	this.breed = breed;
    	this.color = color;
    	this.sex = sex;
    }
    
    var theDog = new Dog("Gabby", "Lab", "chocolate", "female");
    theDog.toString(); // 返回 [object Object]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    6、valueOf()

    6.1、概述

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

    6.2、语法

    object.valueOf();
    
    • 1

    6.3、返回值

    返回值为该对象的原始值。

    6.4、示例

    // Array:返回数组对象本身
    var array = ["ABC", true, 12, -5];
    console.log(array.valueOf() === array); // true
    
    // Date:当前时间距 1970 年 1 月 1 日午夜的毫秒数
    var date = new Date(2013, 7, 18, 23, 11, 59, 230);
    console.log(date.valueOf()); // 1376838719230
    
    // Number:返回数字值
    var num = 15.2654;
    console.log(num.valueOf()); // 15.2654
    
    // 布尔:返回布尔值 true 或 false
    var bool = true;
    console.log(bool.valueOf() === bool); // true
    
    // new 一个 Boolean 对象
    var newBool = new Boolean(true);
    // valueOf() 返回的是 true,两者的值相等
    console.log(newBool.valueOf() == newBool); // true
    // 但是不全等,两者类型不相等,前者是 boolean 类型,后者是 object 类型
    console.log(newBool.valueOf() === newBool); // false
    
    // Function:返回函数本身
    function foo() {}
    console.log(foo.valueOf() === foo); // true
    var foo2 = new Function("x", "y", "return x + y;");
    console.log(foo2.valueOf());
    /*
    ƒ anonymous(x,y
    ) {
    return x + y;
    }
    */
    
    // Object:返回对象本身
    var obj = { name: "张三", age: 18 };
    console.log(obj.valueOf() === obj); // true
    
    // String:返回字符串值
    var str = "http://www.xyz.com";
    console.log(str.valueOf() === str); // true
    
    // new 一个字符串对象
    var str2 = new String("http://www.xyz.com");
    // 两者的值相等,但不全等,因为类型不同,前者为 string 类型,后者为 object 类型
    console.log(str2.valueOf() === str2); // false
    
    • 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

    写在最后

    如果你感觉文章不咋地//(ㄒoㄒ)//,就在评论处留言,作者继续改进;o_O???
    如果你觉得该文章有一点点用处,可以给作者点个赞;\\*^o^*//
    如果你想要和作者一起进步,可以微信扫描二维码,关注前端老L~~~///(^v^)\\\~~~
    谢谢各位读者们啦(^_^)∠※!!!

  • 相关阅读:
    Linux 常用命令
    Linux常见指令
    Redis:redis为什么会分16个库、与数据库关联时是先更新数据库还是先更新缓存、大多数情况为什么删除而不是更新缓存
    scss文件自动导入
    多项式回归算法模拟
    6.区块链系列之本地智能合约部署至测试网与主网
    JAVA自定义注解记录操作日志
    Stable Diffusion半秒出图;VLIW的前世今生;YOLOv5全面解析教程 | AI系统前沿动态
    Flutter 图表组件 charts_flutter_new
    优化模型验证关键代码21:将VRP的三小标决策变量xijk转化为对应的路径序列及各节点的开始服务时间
  • 原文地址:https://blog.csdn.net/weixin_62277266/article/details/126817254