Related methods of Object objects in javascript object-oriented learning

Related methods of Object object

JavaScript Objectprovides many related methods on objects to deal with related operations of object-oriented programming. This chapter describes these methods.

Object.getPrototypeOf()

Object.getPrototypeOfThe method returns the prototype of the parameter object. This is the standard way of getting a prototype object.

var F = function () {};
var f = new F();
Object.getPrototypeOf(f) === F.prototype // true

In the above code, fthe prototype of the instance object is F.prototype.

The following are prototypes for several special objects.

// The prototype of an empty object is Object.prototype
Object.getPrototypeOf({}) === Object.prototype // true
// The prototype of Object.prototype is null
Object.getPrototypeOf(Object.prototype) === null // true
// The prototype of the function is Function.prototype
function f() {}
Object.getPrototypeOf(f) === Function.prototype // true

Object.setPrototypeOf()

Object.setPrototypeOfThe method sets the prototype for the parameter object and returns the parameter object. It takes two parameters, the first is the existing object and the second is the prototype object.

var a = {};
var b = {x: 1};
Object.setPrototypeOf(a, b);
Object.getPrototypeOf(a) === b // true
a.x // 1

In the above code, Object.setPrototypeOfthe method sets athe prototype of the object as an object b, so ait can share bproperties.

newCommands can be Object.setPrototypeOfmocked using methods.

var F = function () {
  this.foo = 'bar';
};
var f = new F();
// Equivalent to
var f = Object.setPrototypeOf({}, F.prototype);
F.call(f);

In the above code, newthe command to create a new instance object can actually be divided into two steps. The first step is to set the prototype of an empty object as a property of the constructor prototype(in the above example F.prototype); the second step is to bind the empty object inside the constructor this, and then execute the constructor so that thisthe methods and properties defined above (The above example is this.foo), are transferred to this empty object.

Object.create()

A common way to generate an instance object is to use newa command to have the constructor return an instance. But in many cases, only one instance object can be obtained, which may not be generated by the constructor at all, so can another instance object be generated from one instance object?

JavaScript provides Object.create()methods to meet this need. This method accepts an object as a parameter, and then uses it as a prototype to return an instance object. The instance fully inherits the properties of the prototype object.

// prototype object
var A = {
  print: function () {
    console.log('hello');
  }
};
// instance object
var B = Object.create(A);
Object.getPrototypeOf(B) === A // true
B.print() // hello
B.print === A.print // true

In the above code, Object.create()the method takes Athe object as the prototype and generates Bthe object. All properties and methods Bare inherited .A

Actually, Object.create()the method can be replaced with the code below.

if (typeof Object.create !== 'function') {
  Object.create = function (obj) {
    function F() {}
    F.prototype = obj;
    return new F();
  };
}

The above code shows that Object.create()the essence of the method is to create an empty constructor F, then let F.prototypethe attribute point to the parameter object obj, and finally return an Finstance, so as to realize objthe attribute that the instance inherits.

The new objects generated by the following three methods are equivalent.

var obj1 = Object.create({});
var obj2 = Object.create(Object.prototype);
var obj3 = new Object();

If you want to generate an object that does not inherit any properties (such as no toString()and methods), you can set the parameter to .valueOf()Object.create()null

var obj = Object.create(null);
obj.valueOf()
// TypeError: Object [object Object] has no method 'valueOf'

In the above code, objthe prototype of the object is nullthat it does not have some Object.prototypeproperties defined on the object, such as valueOf()methods.

When using Object.create()a method, the object prototype must be provided, that is, the parameter cannot be empty or not an object, otherwise an error will be reported.

Object.create()
// TypeError: Object prototype may only be an Object or null
Object.create(123)
// TypeError: Object prototype may only be an Object or null

Object.create()The new object generated by the method dynamically inherits the prototype. Adding or modifying any method on the prototype will be immediately reflected on the new object.

var obj1 = { p: 1 };
var obj2 = Object.create(obj1);

obj1.p = 2;
obj2.p // 2

In the above code, modifying the object prototype obj1will affect the instance object obj2.

In addition to the prototype of the object, Object.create()the method can also accept a second parameter. This parameter is an attribute description object, and the object attribute it describes will be added to the instance object as the object's own attribute.

var obj = Object.create({}, {
  p1: {
    value: 123,
    enumerable: true,
    configurable: true,
    writable: true,
  },
  p2: {
    value: 'abc',
    enumerable: true,
    configurable: true,
    writable: true,
  }
});

// Equivalent to
var obj = Object.create({});
obj.p1 = 123;
obj.p2 = 'abc';

Object.create()The object generated by the method inherits the constructor of its prototype object.

function A() {}
var a = new A();
var b = Object.create(a);

b.constructor === A // true
b instanceof A // true

In the above code, bthe prototype of the object is athe object, so it inherits athe constructor of the object A.

Object.prototype.isPrototypeOf()

The method of the instance object isPrototypeOfis used to determine whether the object is the prototype of the parameter object.

var o1 = {};
var o2 = Object.create(o1);
var o3 = Object.create(o2);

o2.isPrototypeOf(o3) // true
o1.isPrototypeOf(o3) // true

In the above code, o1and o2are o3the prototypes of . This means that as long as the instance object is on the prototype chain of the parameter object, isPrototypeOfthe method returns true.

Object.prototype.isPrototypeOf({}) // true
Object.prototype.isPrototypeOf([]) // true
Object.prototype.isPrototypeOf(/xyz/) // true
Object.prototype.isPrototypeOf(Object.create(null)) // false

In the above code, since Object.prototypeit is at the top of the prototype chain, all kinds of instances are returned true, except for the objects directly inherited nullfrom.

Object.prototype.__proto__

Attributes of the instance object __proto__(two underscores before and after), return the prototype of the object. This property is readable and writable.

var obj = {};
var p = {};

obj.__proto__ = p;
Object.getPrototypeOf(obj) === p // true

The above code sets the object as the prototype of the object through __proto__attributes .pobj

According to the language standard, __proto__the attribute only needs to be deployed by the browser, and other environments may not have this attribute. The two underscores before and after it indicate that it is essentially an internal attribute and should not be exposed to users. Therefore, you should use this attribute as little as possible, but use Object.getPrototypeOf()and Object.setPrototypeOf()to perform read and write operations on prototype objects.

The prototype chain can be __proto__represented very intuitively.

var A = {
  name: 'Zhang San'
};
var B = {
  name: 'Li Si'
};

var proto = {
  print: function () {
    console.log(this.name);
  }
};

A.__proto__ = proto;
B.__proto__ = proto;

A.print() // Zhang San
B.print() // Li Si

A.print === B.print // true
A.print === proto.print // true
B.print === proto.print // true

In the above code, Aboth the object and Bthe prototype of the object are protoobjects, and they all share the methods protoof the object print. That is to say, the method of Aand is calling the method of the object .Bprintprotoprint

Get a comparison of prototype object methods

As mentioned earlier, __proto__the property points to the prototype object of the current object, which is prototypethe property of the constructor function.

var obj = new Object();

obj.__proto__ === Object.prototype
// true
obj.__proto__ === obj.constructor.prototype
// true

The above code first creates a new object obj, and its __proto__properties point to the properties of the constructor ( Objector obj.constructor) prototype.

Therefore, objthere are three ways to obtain the prototype object of the instance object.

  • obj.__proto__

  • obj.constructor.prototype

  • Object.getPrototypeOf(obj)

Of the above three methods, the first two are not very reliable. __proto__Attributes only need to be deployed in browsers, and need not be deployed in other environments. When obj.constructor.prototypemanually changing the prototype object, it may fail.

var P = function () {};
var p = new P();

var C = function () {};
C.prototype = p;
var c = new C();

c.constructor.prototype === p // false

In the above code, the prototype object of the constructor Cis changed p, but the instance object c.constructor.prototypedoes not point to it p. Therefore, when changing the prototype object, it is generally necessary to set constructorproperties at the same time.

C.prototype = p;
C.prototype.constructor = C;

var c = new C();
c.constructor.prototype === p // true

Therefore, it is recommended to use the third Object.getPrototypeOfmethod to obtain the prototype object.

Object.getOwnPropertyNames()

Object.getOwnPropertyNamesThe method returns an array whose members are the keys of all properties of the parameter object itself, excluding inherited property keys.

Object.getOwnPropertyNames(Date)
// ["parse", "arguments", "UTC", "caller", "name", "prototype", "now", "length"]

In the code above, Object.getOwnPropertyNamesthe method returns Dateall its own property names.

Among the properties of the object itself, some are enumerable and some are not. Object.getOwnPropertyNamesThe method returns all key names, whether they can be traversed or not. To get only those attributes that can be traversed, use Object.keysthe method.

Object.keys(Date) // []

The above code shows that Dateall the properties of the object itself cannot be traversed.

Object.prototype.hasOwnProperty()

The method of the object instance hasOwnPropertyreturns a Boolean value, which is used to determine whether a property is defined on the object itself or on the prototype chain.

Date.hasOwnProperty('length') // true
Date.hasOwnProperty('toString') // false

The above code shows that ( how many parameters Date.lengththe constructor can accept) is its own property and an inherited property.DateDateDate.toString

In addition, hasOwnPropertymethods are the only methods in JavaScript that do not traverse the prototype chain when dealing with object properties.

in operator and for...in loop

inThe operator returns a Boolean value indicating whether an object has a certain property. It does not distinguish whether the property is an object's own property or an inherited property.

'length' in Date // true
'toString' in Date // true

inOperators are often used to check for the existence of a property.

To get all traversable properties of an object (whether self or inherited), you can use for...ina loop.

var o1 = { p1: 123 };

var o2 = Object.create(o1, {
  p2: { value: "abc", enumerable: true }
});

for (p in o2) {
  console.info(p);
}
// p2
// p1

In the above code, the properties o2of the object p2are its own and p1the properties are inherited. Both properties will be for...inlooped over.

In order to for...inobtain the properties of the object itself in the loop, you can use hasOwnPropertythe method to judge.

for ( var name in object ) {
  if ( object.hasOwnProperty(name) ) {
    /* loop code */
  }
}

To get all properties of an object (whether self or inherited, and whether enumerable or not), you can use the following function.

function inheritedPropertyNames(obj) {
  var props = {};
  while(obj) {
    Object.getOwnPropertyNames(obj).forEach(function(p) {
      props[p] = true;
    });
    obj = Object.getPrototypeOf(obj);
  }
  return Object.getOwnPropertyNames(props);
}

The above code sequentially obtains objthe "self" attributes of each level of the object's prototype object, thereby obtaining objthe "all" attributes of the object, regardless of whether it is traversable or not.

Below is an example that lists Dateall properties of an object.

inheritedPropertyNames(Date)
// [
//  "caller",
//  "constructor",
//  "toString",
//  "UTC",
//  ...
// ]

copy of object

If you want to copy an object, you need to do the following two things.

  • Make sure that the copied object has the same prototype as the original object.

  • Make sure that the copied object has the same instance attributes as the original object.

The following is the object copy function implemented based on the above two points.

function copyObject(orig) {
  var copy = Object.create(Object.getPrototypeOf(orig));
  copyOwnPropertiesFrom(copy, orig);
  return copy;
}

function copyOwnPropertiesFrom(target, source) {
  Object
    .getOwnPropertyNames(source)
    .forEach(function (propKey) {
      var desc = Object.getOwnPropertyDescriptor(source, propKey);
      Object.defineProperty(target, propKey, desc);
    });
  return target;
}

Another simpler way of writing is to use ES2017 to introduce the standard Object.getOwnPropertyDescriptorsmethod.

function copyObject(orig) {
  return Object.create(
    Object.getPrototypeOf(orig),
    Object.getOwnPropertyDescriptors(orig)
  );
}

reference link

Guess you like

Origin blog.csdn.net/zy_dreamer/article/details/132135133