[ES New Feature 3] Object prototype and prototype chain related methods

1. Object prototype and prototype chain related methods

1.1 Static method (Object call):

  • The Object.setPrototypeOf(obj,prototype) method is used to set the prototype of an instance object (can be null or an object)

  • Object.getPrototypeOf(obj)

​ Note: Before ES5, the instantiated object obtained the prototype object through the __proto__ attribute; in ES5, the statement beginning with __ is not recommended, so the getPropertyOf() method is provided to obtain the prototype object of the object

Native JavaScriptScipt case collection
JavaScript + DOM basic
JavaScript basic to advanced
Canvas game development

1.2 Prototype method (instance call)

This method is the Object.prototype prototype method. Object.prototype is the top-level prototype object of any object on the prototype chain. Any object defined in JS (custom objects, array objects, etc. can call sub-methods).

  • The isPrototypeOf() method is used to test whether an object exists on the prototype chain of another object.
  • The hasOwnProperty() method returns a Boolean value indicating whether the object has the specified property in its own properties (that is, whether it has the specified key).
<body>
<ul>
    <li>111</li>
    <li>222</li>
    <li>333</li>
    <li>444</li>
</ul>
</body>
<script>
    // 获取类数组对象
    var lis = document.getElementsByTagName("li");

    // 定义数组
    var arr = [10,20,30,40];

    // 自定义对象
    var obj = {name:"张三"}

    // 查看Array.prototype这个原型是哪个实例化对象的原型
    console.log(Array.prototype.isPrototypeOf(lis));//false
    console.log(Array.prototype.isPrototypeOf(obj));//false
    console.log(Array.prototype.isPrototypeOf(arr));//true

    // 查找过程中,会查找整个原型链
    console.log(Object.prototype.isPrototypeOf(lis));//true
    console.log(Object.prototype.isPrototypeOf(obj));//true
    console.log(Object.prototype.isPrototypeOf(arr));//true

    // 获取实例化对象 arr 的原型对象
    // 原始方式
    console.log(arr.__proto__);//[constructor: ƒ, concat: ƒ, copyWithin: ƒ, fill: ƒ, find: ƒ, …]
    // ES5方式
    console.log(Object.getPrototypeOf(arr));//[constructor: ƒ, concat: ƒ, copyWithin: ƒ, fill: ƒ, find: ƒ, …]
    // 对比
    console.log(arr.__proto__ === Object.getPrototypeOf(arr));//true

   
    // 设置实例化对象 arr 的原型对象  可以为null 也可以是一个对象  会修改整个原型链
    Object.setPrototypeOf(arr,null);
    console.log(Object.getPrototypeOf(arr));//null

    Object.setPrototypeOf(arr,{a:10});
    console.log(Object.getPrototypeOf(arr));//{a:10}

    // 构造函数的原型不变  只是实例化对象原型指向改变
    console.log(Array.prototype);//[constructor: ƒ, concat: ƒ, copyWithin: ƒ, fill: ƒ, find: ƒ, …]
</script>
  • The __proto__ property is an accessor property (a getter function and a setter function) that exposes the internals of the object accessed through it [[Prototype]](an object or null). proto properties can also be created using object[[Prototype]] in object literal definitions, as Object.create()an alternative to .

1.3 Method of manipulating attributes (Object call)

The **Object.getOwnPropertyNames()** method returns an array consisting of the property names of all own properties of the specified object (including non-enumerable properties but excluding properties with Symbol values ​​as names).

The Object.getOwnPropertySymbols() method returns an array of all Symbol properties of a given object itself.

Object.hasOwn() returns if the specified object itself has the specified property true. This method returns if the property is inherited or does not exist false.

Note: Object.hasOwn() Intended to replace Object.hasOwnProperty().

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

// 数组对象
var arr = ["a", "b", "c"];
console.log(Object.getOwnPropertyNames(arr).sort()); // ["0", "1", "2", "length"]

// Symbols 
var obj = {};
var a = Symbol("a");
var b = Symbol.for("b");
obj[a] = "localSymbol";
obj[b] = "globalSymbol";
var objectSymbols = Object.getOwnPropertySymbols(obj);

// hasOwn()
const example = {};
Object.hasOwn(example, 'prop');   // false - 'prop' has not been defined

example.prop = 'exists';
Object.hasOwn(example, 'prop');   // true - 'prop' has been defined

2. Object related methods

2.1 Object.preventExtensions() cancels object extensibility

The Object.preventExtensions(obj) method is used to cancel the extensibility of the object

Object.isExtensible(obj) determines whether the object has canceled its extensibility. The return value is a Boolean value. Returning a true object can extend properties, and returning a false object cannot extend properties.

Note: When an object is de-expandable, the object can no longer extend its attributes, but it can modify and delete its attributes.

var obj = {
    a:1,
    b:2
}

console.log("取消对象可拓展性前对象:",obj);

// 取消对象拓展
Object.preventExtensions(obj);

// 拓展属性
obj.c = 3;

// 删除属性
delete obj.a;

// 修改属性值
obj.b = 22;

// 判断对象是否可拓展
console.log(Object.isExtensible(obj));//true

console.log("取消对象可拓展性后并操作属性后的对象:",obj);

2.2 Object.seal() closed object

Object.seal(obj) closes the properties of the object

Object.isSealed(obj) determines whether the object property is sealed. Return value Boolean value, return true if the object is closed, return false if the object is not closed

Note: When an object is closed, attributes cannot be expanded or deleted, but attributes can be modified.

var obj = {
    a:1,
    b:2
}

console.log("封闭前对象:",obj);

// 封闭对象
Object.seal(obj);

// 拓展属性
obj.c = 3;

// 删除属性
delete obj.a;

// 修改属性值
obj.b = 22;

// 判断对象是否被封闭
console.log(Object.isSealed(obj));//true

console.log("封闭后并操作属性后的对象:",obj);

2.3 Object.freeze() freezes the object

The Object.freeze(obj) method is used to freeze the properties of the object

The Object.isFrozen(obj) method is used to determine whether the object property is frozen. Return value A boolean value returns true and the object is frozen, returns false and the object is not frozen

Note: When an object is frozen, the properties of the object cannot be expanded, modified or deleted

var obj = {
    a:1,
    b:2
}

console.log("冻结前对象:",obj);

// 冻结对象
Object.freeze(obj);

// 拓展属性
obj.c = 3;

// 删除属性
delete obj.a;

// 修改属性值
obj.b = 22;

// 判断对象是否被冻结
console.log(Object.isFrozen(obj));//true

console.log("冻结后并操作属性后的对象:",obj);

2.4 Object.create() creates objects

The Object.create(proto, [propertiesObject]) method creates a new object using an existing object as a prototype for the newly created object.

  • parameter

    • proto The object that should be the prototype of the newly created object. can be null
    • propertiesObject optional. Specifies the property descriptor to add to the newly created object, along with the corresponding property name. These properties correspond to the properties of the object properties in the second parameter of Object.defineProperties().
  • Return Value A new object with the specified prototype object and properties.

// 学过的创建对象的方式
// var obj = {};
// var obj1 = new Object();
// var obj2 = Object();

// ES5新增创建一个空对象  第一个参数新创建对象的原型设置为null
// var obj3 = Object.create(null);
// console.log(obj3)

//使用Object.create() 来创建一个对象,第一个参数原型对象为一个常量对象
// var obj = Object.create({
//     sayHi:function(){
//         console.log("Hello");
//     }
// })

// 第一个参数为空,第二个参数为 要创建对象的空对象的属性特性描述(类似于Object.defineProperty()设置的对象特性)
// var obj = Object.create(null,{
//     name:{
//         // 配置值
//         value:"张三",
//         // 配置是否可写
//         writable:false,
//         // 配置是否可枚举
//         enumerable:false
//     },
//     age:{
//         // 配置值
//         value:10,
//          // 配置是否可写
//          writable:false,
//     }
// })
// console.log(obj);
// console.log(obj.name);
// // 通过这种对象特性的方式创建的对象,默认属性不能被删除 修改
// obj.name = "haha";
// delete obj.age;
// console.log(obj);
// console.log(obj.name);


// 创建一个对象,并能继承另外一个对象的方法;将一个对象作为另外一个对象的原型
// 创建需要的原型对象
var prototype = {
    sayHi:function(){
        console.log("Hello");
    }
}

// 创建需要的特性属性对象
var options = {
    name:{
        // 配置值
        value:"张三",
        // 配置是否可写
        writable:false,
        // 配置是否可枚举
        enumerable:false
    },
    age:{
        // 配置值
        value:10,
         // 配置是否可写
         writable:false,
    }
}

// 两者组合创建对象
var obj = Object.create(prototype,options);

console.log(obj)//查看原型
obj.sayHi();

2.5 Object.create() perfect inheritance

// 定义父类
function People(name,sex,age){
    this.name = name;
    this.sex = sex;
    this.age = age;
}

// 原型中定义方法
People.prototype.sayHi = function(){
    return "姓名:" + this.name + ",性别:" + this.sex + ",年龄:" + this.age;
}

People.prototype.sayHello = function(){
    return "Hello";
}

// 定义子类
function Student(name,sex,age,score){
    // applay实现继承(改变调用对象
    People.apply(this,arguments);

    // 定义子类拓展的属性
    this.score = score;
}

// var p = new People();
// delete p.name;
// delete p.sex;
// delete p.age;

// 子类继承父类中的方法 必须要使用原型继承 将子类的原型指向父类的实例
// Student.prototype = new Student();

// 使用Object.create()优化继承
Student.prototype = Object.create(People.prototype);

// 原型继承会造成结构的紊乱,将原型对象的构造函数手动改回到Student
Student.prototype.constructor = Student;

// 实例化对象
var s = new Student("张三","男",23,100);

// 调用父类原型中的方法
console.log(s.sayHi());

/*
* 原型继承,子类的原型就是父类的实例,这种方式会在子类的原型中多出几个无用的属性
* 此时,会在子类的原型中多出几个属性:name:undefined,age:undifined,sex:undefined
* 如果不考虑寄生组合继承这种方式进行优化,ES5还提供了Object.create()方法来优化
**/

2.6 Encapsulation and implementation of the Object.create() method

// 定义父类
function People(name,sex,age){
    this.name = name;
    this.sex = sex;
    this.age = age;
}

// 原型中定义方法
People.prototype.sayHi = function(){
    return "姓名:" + this.name + ",性别:" + this.sex + ",年龄:" + this.age;
}

People.prototype.sayHello = function(){
    return "Hello";
}

// 定义子类
function Student(name,sex,age,score){
    // applay实现继承(改变调用对象
    People.apply(this,arguments);

    // 定义子类拓展的属性
    this.score = score;
}

// 取消Object.create方法
Object.create = null;
// 重新自定义 create 方法,实现相同的功能
Object.create = function(prototype){
    // 定义一个构造函数
    var F = function(){

    }

    // 将F的原型指向传入的原型
    F.prototype = prototype;

    // 返回F的实例
    return new F();
}

// 使用Object.create方法实现继承
Student.prototype = Object.create(People.prototype);

// 实例化对象
var s = new Student("张三","男",23,100);
console.log(s.sayHi());

2.7 Object.entries() and other methods that return enumerable arrays

The Object.entries() method returns an array of key-value pairs for a given object's own enumerable properties, for...inarranged in the same order as returned when using a loop to traverse the object (the difference is that the for-in loop also enumerates the prototype chain. Attributes).

The Object.keys() method returns an array of a given object's own enumerable properties, in the same order that the property names in the array would be returned when looping through the object normally.

The Object.values() method returns an array of all enumerable property values ​​for a given object itself, in the for...insame order as using the loop (the difference is that the for-in loop enumerates properties in the prototype chain).

const info = {
	name: "Jack",
    country: "Russia",
    age: 35
}

// 使用 Object.keys() 将对象所有自身可枚举属性收集到一个新数组中
const keys = Object.keys(info);

// 使用 Object.values() 将对象所有自身可枚举值收集到一个新数组中
const values = Object.values(info);

// 使用 Object.entries() 将对象所有自身可枚举所有键值对收集到一个新数组中
const keyVals = Object.entries(info)
// 使用 for...of 遍历自身的键值对(key 和 value)
for (const [key, value] of keyVals) {
  console.log(`${key}: ${value}`);
}

2.8 Object.assign()

The Object.assign(target, ...sources) method copies all enumerable ( Object.propertyIsEnumerable()returns true) own ( Object.hasOwnProperty()returns true) properties from one or more source objects to the target object, returning the modified object. If the target object has the same key as the source object , the properties in the target object will be overwritten by the properties in the source object.

Parameters : target target object, the object that receives the properties of the source object, and is also the modified return value.

​ sources Source object containing the properties to be merged.

Return value : target object

Points to note :

  1. For deep copies , other methods need to be used because Object.assign()only attribute values ​​are copied. If the source object is a reference to an object, it only copies its reference value (address).
  2. Prototype-chained properties and non-enumerable properties cannot be copied.
'use strict';

// Object.assign() 属于浅拷贝
let obj1 = { a: 0 , b: { c: 0}};
let obj2 = Object.assign({}, obj1);
console.log(JSON.stringify(obj2)); // { "a": 0, "b": { "c": 0}}

obj1.a = 1;
console.log(JSON.stringify(obj1)); // { "a": 1, "b": { "c": 0}}
console.log(JSON.stringify(obj2)); // { "a": 0, "b": { "c": 0}}

obj2.a = 2;
console.log(JSON.stringify(obj1)); // { "a": 1, "b": { "c": 0}}
console.log(JSON.stringify(obj2)); // { "a": 2, "b": { "c": 0}}

obj2.b.c = 3;
console.log(JSON.stringify(obj1)); // { "a": 1, "b": { "c": 3}}
console.log(JSON.stringify(obj2)); // { "a": 2, "b": { "c": 3}}

// 深拷贝(深度克隆)
obj1 = { a: 0 , b: { c: 0}};
let obj3 = JSON.parse(JSON.stringify(obj1));
obj1.a = 4;
obj1.b.c = 4;
console.log(JSON.stringify(obj3)); // { "a": 0, "b": { "c": 0}}


// 合并对象
const o1 = { a: 1 };
const o2 = { b: 2 };
const o3 = { c: 3 };

const obj = Object.assign(o1, o2, o3);
console.log(obj); // { a: 1, b: 2, c: 3 }
console.log(o1);  // { a: 1, b: 2, c: 3 }, target object itself is changed.


//合并相同属性的对象
const o1 = { a: 1, b: 1, c: 1 };
const o2 = { b: 2, c: 2 };
const o3 = { c: 3 };

const obj = Object.assign({}, o1, o2, o3);
console.log(obj); // { a: 1, b: 2, c: 3 }

2.9 Object.is() determines whether two values ​​are the same value.

The Object.is(value1, value2) method determines whether two values ​​are the same value. If any of the following conditions are met, the two values ​​​​are equal:

  • Allundefined
  • Allnull
  • all trueor bothfalse
  • They are all strings of the same length, the same characters, and arranged in the same order.
  • They are all the same object (meaning they are all value references to the same object)
  • are all numbers and
    • All+0
    • All-0
    • AllNaN
    • are all the same value, non-zero and neitherNaN

Object.is()Different from ==. ==The operator casts the variables on both sides (if they are not of the same type) before judging equality (this behavior will be "" == falsejudged as true), Object.iswithout coercing the values ​​of both sides.

Object.is()Also ===not the same as . The difference is that they treat signed zero and NaN differently, for example, ===the operators (and also ==the operator) treat the numbers -0and +0as equal, but treat Number.NaNand NaNas unequal.

// 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

Guess you like

Origin blog.csdn.net/qq_39335404/article/details/132575784