On how to create JavaScript objects _javascript skills

Source: Internet
Author: User
Tags instance method hasownproperty advantage

When you create objects from the object constructor or object literal, a large number of duplicate code is generated when you create many objects using the same interface. In order to simplify, the factory model was introduced.

Factory mode

function Createperson (name, age, Job) {
  var obj = new Object ();
  Obj.name = name;
  Obj.age = age;
  Obj.job = job;
  Obj.sayhello () {
    alert (this.name);
  };
  return obj;
}
var P1 = Createperson ("Xxyh", "programmer");
var P2 = Createperson ("Zhangsan", "student");

This way of creating objects greatly simplifies the code, but there is also a lack of certainty about the type of object. To solve this problem, the following pattern appears.

Constructor pattern

Create a custom constructor that defines the properties and methods of the custom object type.

function person (name, age, Job) {
  this.name = name;
  This.age = age;
  This.job = job;
  This.sayname = function () {
    alert (this.name);}
  ;
} var p1 = new Person ("Xxyh", "programmer");
var p2 = new Person ("Jack", "student");

In the example above, the person () replaces Createperson (), and there are several differences:

• Create objects without displaying them;

• Assign properties and methods directly to the This object

• No return statement

To create a person object, you must use the new operator. is divided into 4 steps:

• Create a new object

• Assign a constructor's scope to a new object

• Execute the code in the constructor

• Return new Object

P1 and P2 each hold an instance of person.

Alert (P1.constructor = = person);  True
alert (p2.constructor = = person);  True

It is best to use instanceof when detecting types:

Alert (P1 instanceof Object);  True
alert (P1 instanceof person);  True
alert (P2 instanceof Object);  True
alert (P2 instanceof person);  True

Both P1 and P2 are instances of object because all objects inherit from object.

2.1 Constructor as a function

Use the Var person as a constructor
= new Person ("Xxyh", "programmer");
Person.sayname ();  "Xxyh"

//as ordinary function person
("Zhangsan", "student");  Add to Window
window.sayname ();  ' Zhangsan '

//calling
var obj = new Object ()
in the scope of another. Person.call (obj, "Jack", "Manager");
Obj.sayname ();  "Jack", obj has all the properties and methods

2.2 Problems with constructors

The problem with constructors is that each method is recreated on each instance. Both P1 and P2 have a sayname () method, but they are not instances of a function. In JavaScript, a function is an object, so each definition of a function instantiates an object.

Constructors can also be defined like this:

function person (name, age, Job) {
  this.name = name;
  This.age = age;
  This.job = job;
  This.sayname = new Function ("Alert (this.name)");
}

Therefore, the functions of the same name on different instances are not equal:

Alert (P1.sayname = = p2.sayname);  False

However, creating two functions with the same functionality is redundant and does not require that the function be bound to a particular object before the code is executed.

function person (name, age, Job) {
  this.name = name;
  This.age = age;
  This.job = job;
  This.sayname = Sayname;
}
function Sayname () {
  alert (this.name);
}
var p1 = new Person ("Xxyh", "programmer");
var p2 = new Person ("Jack", "student");

This moves the definition of sayname () to the outside of the constructor, and then sets the property sayname to the global sayname function inside the constructor. In this way, Sayname contains pointers to functions, p1 and P2 share the same sayname () function defined in the global scope.

However, there is a new problem with this: a function defined in a global scope can only be invoked by an object. And if the object defines many methods, the reference type loses its encapsulation.

Prototype chain mode

Each function has a prototype (prototype) attribute, which is a pointer to an object. The purpose of this object is to include properties and methods that can be shared by all instances of a particular type . Prototype is the prototype object of that object instance that was created by calling the constructor. The advantage of using a prototype object is that all object instances can share the properties and methods it contains. This means that you do not have to define the information for an object instance in the constructor, but instead add that information to the prototype object.

function person () {
}

Person.prototype.name = "Xxyh";
Person.prototype.age =;
Person.prototype.job = "Programmer";
Person.prototype.sayName = function () {
  alert (this.name);
};

var person1 = new Person ();
Person1.sayname (); "Xxyh"
var person2 = new Person ();
Person2.sayname (); "Xxyh"

alert (person1.sayname = = person2.sayname);//True

3.1 Understanding the Prototype object

As soon as a new function is created, a prototype property is created for the function, which points to the prototype object of the function. By default, all prototype objects will automatically get a constructor property. This property contains a pointer to the function where the prototype property resides. Person.prototype.constructor point to Person.

When a constructor is called to create an instance, an instance's interior will contain a pointer to the constructor's prototype object (internal property), called [[Prototype]]. Accessed via _proto_ in Firefox, Safari and Chrome. This connection exists between the instance and the stereotype object of the constructor, not between the instance and the constructor.

The following illustration shows the relationships between objects:

The Person.prototype points to the prototype object, and the Person.prototype.constructor refers back to the person. In addition to the constructor attribute in the prototype, there are other added properties. The person instance contains an internal property that points only to Person.prototype, which is not directly related to the constructor.

Although [[Prototype]] cannot be accessed, the isPrototypeOf () method can be used to determine whether the relationship exists between objects.

Alert (Person.prototype.isPrototypeOf (Person1));  True
alert (Person.prototype.isPrototypeOf (Person2));  True

When you read an object's properties, a search is performed, and the target is a property with the given name. The search starts first from the object instance itself. The search begins with the object instance itself, if a property with the given name is found in the instance, returns the value of the property, or, if not found, continues to search the prototype object that the pointer points to, looking for the property of the given name in the prototype object. If this property is found in the prototype object, the value of the property is returned.

You can access values that are stored in the prototype through an object instance, but you cannot override the values in the prototype through an object instance . If you add a property in the instance with the same name as a property in the instance prototype, the property will mask the properties in the prototype.

function person () {
}

Person.prototype.name = "Xxyh";
Person.prototype.age = "a";
Person.prototype.job = "Programmer";
Person.prototype.sayName = function () {
  alert (this.name);
};

var person1 = new Person ();
var person2 = new Person ();

Person1.name = "Oooo";
alert (person1.name);  "Oooo"
alert (person2.name);  "Xxyh"

In the example above, the Name property in Person1 masks the name attribute in the prototype.

When an object instance adds a property, this property masks the property of the same name that is saved in the prototype object. This means that the existence of this property prevents access to that attribute in the prototype. Use Delete to complete the Delete instance property.

function person () {
}

Person.prototype.name = "Xxyh";
Person.prototype.age = "a";
Person.prototype.job = "Programmer";
Person.prototype.sayName = function () {
  alert (this.name);
};

var person1 = new Person ();
var person2 = new Person ();

Person1.name = "Oooo";
alert (person1.name);  "Oooo"
alert (person2.name);  "Xxyh"

delete person1.name;
alert (person1.name);  "Xxyh"

hasOwnProperty () can detect whether an attribute exists in the instance or in the prototype.

function person () {
}

Person.prototype.name = "Xxyh";
Person.prototype.age = "a";
Person.prototype.job = "Programmer";
Person.prototype.sayName = function () {
  alert (this.name);
};

var person1 = new Person ();
var person2 = new Person ();

Alert (Person1.hasownproperty ("name"));  False

Person1.name = "Oooo";
Alert (Person1.hasownproperty ("name"));  True

The following diagram shows the relationship between implementations of different situations and prototypes:

3.2 Prototypes with in operators

Using the IN operator: used separately, in the for-in loop. When used alone, the in operator returns True when the given property is accessible through an object, whether the property exists in the instance or in the prototype.

function person () {

}
Person.prototype.name = "Xxyh";
Person.prototype.age = "a";
Person.prototype.job = "Programmer";
Person.prototype.sayName = function () {
  alert (this.name);
};

var person1 = new Person ();

Alert ("name" in Person1);  True

person1.name = "Oooo";
Alert ("name" in Person1);  True

Combined with the previous hasownproperty () feature, you can determine whether an attribute is a property in the prototype or an attribute in the instance. If the In operator returns True and hasOwnProperty returns False, the property is a property in the prototype.

function Hasprototypeproperty (object, name) {return
  !object.hasownproperty (name) && (name in object);
}

Next, look at the use of Hasprototypeproperty ():

function person () {
}

Person.prototype.name = "Xxyh";
Person.prototype.age = "a";
Person.prototype.job = "Programmer";
Person.prototype.sayName = function () {
  alert (this.name);
};

var person = new person ();
Alert (Hasprototypeproperty (person, "name"));  True
person.name = "Oooo";

Alert (Hasprototypeproperty (person, "name"));  False

When you use the for-in loop, you return all enumerable properties that can be accessed through the object, including the properties in the instance and the properties in the stereotype. The instance property of the block that is not enumerated in the prototype (that is, [[[Enumerable]] marked as false) is also returned in for-in because the attributes defined by the developer are enumerable.

To get all the enumerable instance properties on an object, you can use the Object.keys () method.

function person () {
}

Person.prototype.name = "Xxyh";
Person.prototype.age = "a";
Person.prototype.job = "Programmer";
Person.prototype.sayName = function () {
  alert (this.name);
};

var keys = Object.keys (Person.prototype);
alert (keys);      Name, age, Job, Sayname

var p1 = new Person ();
P1.name = "Oooo";
P1.age =;
var P1_keys = Object.keys (p1);
alert (P1_keys);     Name, age

If you need to get all instance properties, you can use the Object.getownpropertynames () method

var keys = object.getownpropertynames (Person.prototype);
alert (keys);  "Constructor,name,age,job,sayname"

3.3 Simpler prototype syntax

To streamline input, rewrite the consolidated prototype object with an object literal that contains all the properties and methods.

function person () {   
}

person.prototype = {
  name: "Xxyh",
  age:18,
  job: "Programmer",
  sayname: function () {
    alert (this.name);
  }
};

The above sets the person.prototype to be equal to a new object created in the literal form of an object. The result is the same, but the constructor property is not pointing to person.

The correct result can be returned through instanceof, but constructor cannot determine the type of the object:

var boy = new Person ();
Alert (boy instanceof Object);    True
alert (boy instanceof person);    True
alert (boy.constructor = = person);  False
alert (boy.constructor = = Object);  True

You can set constructor values in the following ways:

function person () {
}

person.prototype = {
  Constructor:person,
  name: "Xxyh",
  age:18,
  Job: "Programmer",
  sayname:function () {
    alert (this.name);
  }
;

3.4 Dynamics of the prototype chain

Since the process of locating a value in a prototype is a search, any modifications made to the prototype object are reflected on the instance. But if you rewrite the entire prototype object, the result is different. Calling a constructor adds a [[prototype]] pointer to the original prototype for the instance, and modifying the stereotype to another object is tantamount to cutting off the constructor's connection to the original prototype. the pointer in the instance points only to the stereotype, not to the constructor.

function person () {
}

var boy = new Person ();
Person.prototype = {
  Constructor:person,
  name: "Xxyh",
  age:29,
  job: "Programmer",
  Sayname:func tion () {
    alert (this.name);
  }
};

Boy.sayname ();  Error

The specific process is as follows:

As you can see from the above, rewriting the prototype object cuts off the connection between the existing prototype and any previously existing object instances, which refer to the original prototype.

3.5 prototype of native objects

All native reference types define a method on the stereotype of a constructor. The prototype of the native object allows you to not only get the default method, but also define a new method.

String.prototype.startsWith = function (text) {return
  this.indexof (text) = 0;
};

var msg = "Good Morning";
Alert (Msg.startswith ("good")); True

3.6 Problems with prototype objects

There are two problems with the prototype pattern:

• The same property values are obtained by default.

• All attributes in the prototype are shared by the instance

Let's look at an example:

function person () {

}

person.prototype = {
  Constructor:person,
  name: "Xxyh",
  age:18,
  job: " Programmer ",
  friends:[" John "," Dick "],
  sayname:function () {
    alert (this.name);
  }
;

var p1 = new Person ();
var p2 = new Person ();

P1.friends.push ("Harry");

alert (p1.friends);         John, Dick, Harry
alert (p2.friends);         John, Dick, Harry
alert (p1.friends = = p2.friends);  True

The above is added by P1.friends, because the friends array exists in Person.prototype, so it is reflected in p2.friends. However, the example is generally to have their own all the attributes.

Combining constructor patterns with prototype patterns

Constructor patterns are used to define instance properties, which are used to define methods and shared properties. In this way, each instance has a copy of its own instance attribute, but it also shares a reference to the method.

function person (name, age, Job) {
  this.name = name;
  This.age = age;
  This.job = job;
  This.friends = ["John", "Dick"];
}
Person.prototype = {
  Constructor:person,
  sayname:function () {
    alert (this.name);
  }
}

var p1 = new Person ("The Rustle of the cold", "programmer");
var p2 = new Person ("Quebec pull", 10, "Catch Demon");

P1.friends.push ("Harry");
alert (p1.friends);         John, Dick, Harry
alert (p2.friends);         John, Dick
alert (p1.friends = = p2.friends);  False
alert (p1.sayname = = p2.sayname);  True

In the example above, the instance property is defined in the constructor, and the shared property constructor and Method Sayname () are defined in the prototype. The p1.friends modification does not affect the results of the p2.friends.

Dynamic Prototyping Mode

The dynamic prototyping pattern encapsulates all the information in the constructor, and by initializing the prototype in the constructor, it retains the advantage of using both constructors and prototypes. This means that you can decide whether to initialize a prototype by checking whether a method that should exist is valid.

function person (name, age, Job) {
    
  //attribute
  this.name = name;
  This.age = age;
  This.job = job;
  
  Method
  if (typeof this.sayname!= "function") {
    Person.prototype.sayName = function () {
      alert (this.name); 
   }
  }
}

This is only added to the prototype when the Sayname () method does not exist, and will only be executed when the constructor is first invoked.

Parasitic constructor patterns

The idea of this pattern is to create a function that encapsulates the code that creates the object and then returns the newly created object.

function person (name, age) {
  var obj = new Object ();
  Obj.name = name;
  Obj.age = age;
  Obj.sayname = function () {
    alert (this.name);
  }
  return obj;
}

var boy = new Person ("Xxyh", "programmer");
Boy.sayname ();

Note: First, there is no relationship between the returned object and the constructor or the stereotype property of the constructor; The constructor returns an object that is not different from the object created outside the constructor. You cannot rely on the instanceof operator to determine the object type.

Secure constructor Mode

A secure object is an object that has no public properties and whose methods do not refer to this. A secure constructor follows a pattern similar to a parasitic constructor, but there are two different points:

• The instance method of the newly created object does not refer to this;

• Call constructors without using the new operator

Rewrite the person constructor as follows:

function person (name, age, Job) {
  var obj = new Object ();
  Obj.sayname = function () {
    alert (name);
  };

  return obj;
}
function person (name, age, Job) {
  var obj = new Object ();
  Obj.sayname = function () {
    alert (name);
  };

  return obj;
}

The above article on the creation of JavaScript object is a small series to share all the content of everyone, hope to give you a reference, but also hope that we support the cloud-dwelling community.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.