JavaScript quest: powerful prototypes and prototype chains

Source: Internet
Author: User
Tags hasownproperty function calculator

The foo variable is the for (var i in Foo) {    if (foo.hasownproperty (i)) {        console.log (i)) {if (i)    }, in the above example;}

JavaScript does not include the traditional class inheritance model, but rather uses the Prototypal prototype Model.

Although this is often referred to as a disadvantage of JavaScript, in fact the prototype-based inheritance model is more powerful than the traditional class Inheritance. Implementing the traditional class inheritance model is very easy, but it is much more difficult to implement the prototype inheritance in JavaScript.

Because JavaScript is the only widely used prototype-based language, it takes time to understand the differences between the two inheritance patterns, and today we'll look at prototypes and prototype Chains.

Prototype

10 Years Ago. When I first learned javascript, I used to write code in the following ways:

<pre name= "code" class= "javascript" >var decimaldigits = 2,tax = 5;function Add (x, y) {    return x + y;} function Subtract (x, y) {    return x-y;} Alert (add (1, 3));


By running each function to get the results, after learning the Prototype. We can use the following methods to beautify the code, for Example.

How to use prototypes 1

Before using the Prototype. We need to make a small change to the code first:

var Calculator = function (decimaldigits, tax) {    this.decimaldigits = decimaldigits;    This.tax = tax;};


And then. The prototype of the Calculator object is set by assigning a value object literal to the prototype property of the calculator object.

Calculator.prototype = {    add:function (x, y) {        return x + y;    },    subtract:function (x, y) {        return x -y;    }};/ /alert ((new Calculator ()). add (1, 3));
In this way, we will be able to call the Add method to calculate the result after the new calculator object.


How to use Prototypes 2

Another way is to assign a value using the expression that the function runs immediately when the value prototype is prototype, such as the following format:

Calculator.prototype = function () {} ();
its advantages are already known in the previous Post. is to be able to encapsulate the private function, through the form of return to expose a simple use name, in order to achieve public/private Effect. The changed code is as Follows:
Calculator.prototype = function () {    add = function (x, Y) {        return x + y;    },    subtract = function (x, Y) {        return x-y;    }    return {        add:add,        subtract:subtract    }} (),//alert ((new Calculator ()). add (11, 3));


in the same way, we were able to call the Add method after the new Calculator object to evaluate the Result. Step declaration

When using the prototype Above. One limitation is that the prototype object is set at Once. Let's take a look at how to set each property of the Prototype.

var basecalculator = function () {    //declare A decimal place for each instance    this.decimaldigits = 2;};        Using prototypes to extend 2 object methods to Basecalculator BaseCalculator.prototype.add = function (x, y) {    return x + y;}; BaseCalculator.prototype.subtract = function (x, y) {    return x-y;};


First of all. A Basecalculator object was Declared. The constructor initializes the attribute decimaldigits of a decimal place, and then sets 2 functions by the prototype property, each of which is add (x, y) and subtract (x, y). Of course you can also use the 2 different ways mentioned above, our main purpose is to see how to set the Basecalculator object to the real calculator prototype.

var basecalculator = function () {    this.decimaldigits = 2;};  Basecalculator.prototype = {    add:function (x, y) {        return x + y;    },    subtract:function (x, y) {        return x-y;    }};

Once you've created the above code, let's start:

var Calculator = function () {    //declare A tax number for each instance    This.tax = 5;};        Calculator.prototype = new Basecalculator ();

We can see that the prototype of calculator is pointing to an instance of basecalculator, with the intention of having calculator integrate its add (x, y) and subtract (x, Y) 2 function, and the other is, Because its prototype is an instance of basecalculator, no matter how many Calculator object instances you create, their prototypes point to the same instance.



The Code Above. After Execution. We can see that because Calculator's prototype is on an instance of basecalculator, you can access the value of his decimaldigits property, So what if I don't want calculator to visit the property values declared in Basecalculator's constructor? This:

var Calculator = function () {    this.tax= 5;}; Calculator.prototype = basecalculator.prototype;

By assigning the prototype of the Basecalculator to the calculator prototype, so that you do not have access to the Decimaldigits value on the calculator instance, Suppose you visit the following code, which will raise the Error.

var calc = new Calculator (); alert (calc.add (1, 1)); alert (calc.decimaldigits);


Rewriting prototypes

In the use of Third-party JS class libraries, often sometimes they define the prototype method is not enough to meet our NEEDS. But this kind of library is inseparable from it. So at this point we need to rewrite one or more attributes or function in their prototype. We are able to override the previous add function by continuing to declare the same add code in the form of the overlay rewrite, such as the Following:

The add () function Calculator.prototype.add = function (x, y) {    return x + y + this.tax;}, covering the preceding Calculator; var calc = new Calculator (); alert (calc.add (1, 1));


Such We calculated the result is more than the original value of a tax. however, It is important to note that the rewrite code needs to be put in the end, so that the ability to overwrite the previous Code.

Prototype chain

Before we put the prototype chain, we'll go through the code:

function Foo () {    this.value = 42;} Foo.prototype = {    method:function () {}};function Bar () {}//sets The prototype property of bar as an instance object of Foo Bar.prototype = new Foo (); Bar.prototype.foo = ' Hello world ';//fix Bar.prototype.constructor for Bar itself Bar.prototype.constructor = bar;var test = new Bar ()///create a new instance of Bar//prototype chain test [instance of bar]    bar.prototype [instance of foo]         {foo: ' Hello world '}        foo.prototype            { Method: ...};            Object.prototype                {toString: .../* etc. */};


In the example Above. The test object inherits from Bar.prototype and Foo.prototype. therefore, It can access the prototype method of Foo.

At the same time, it can also access the attribute value of the Foo instance defined on the Prototype. It is important to note that new bar () does not create an instance of Foo, but instead uses that instance of its prototype repeatedly, so all Bar instances share the same value Property.

Property Lookup

When you find the properties of an Object. JavaScript will traverse the prototype chain up. Until a property of the given name is found, the lookup arrives at the top of the prototype Chain-that is object.prototype-but still does not find the specified property, it returns undefined, Let's take a look at the example:

function foo () {    this.add = function (x, y) {        return x + y;    }} Foo.prototype.add = function (x, y) {    return x + y + 10;} Object.prototype.subtract = function (x, y) {    return x-y;} var f = new Foo (); alert (f.add (1, 2)); The result is 3. Instead of 13alert (f.subtract (1, 2)); The result is-1


Executed through Code. We found that subtract is installing what we call upward lookup to get results, but the Add method is a little Different. This is what I want to emphasize, that is, the property is looking for its own properties, assuming that no more prototypes are Found. No more, go up again. Stuck to the prototype of Object. so, at some level. Efficiency is also an issue when traversing a property with a for in Statement.

Another point we should note is that we are able to assign values regardless of the type of object to the prototype, but not the value of the atomic Type. For example, The following code is invalid:

function Foo () {}foo.prototype = 1; Invalid


hasOwnProperty function

hasOwnProperty is a method of Object.prototype. It's a good thing, he can infer whether an object includes its own definition attribute rather than the property on the prototype chain, since hasOwnProperty is the only function in JavaScript that handles properties but does not look for a prototype chain.

Change Object.prototypeObject.prototype.bar = 1; var foo = {goo:undefined};foo.bar; 1 ' Bar ' in foo; Truefoo.hasownproperty (' Bar '); Falsefoo.hasownproperty (' Goo '); True


Only hasownproperty can give correct and desired results, which is useful when traversing the properties of an Object. There is no other way to exclude properties on the prototype chain, rather than on the object itself.

But the disgusting thing is that JavaScript does not protect hasOwnProperty from being illegally occupied, so assuming that an object happens to have this property, you need to use an external hasownproperty function to get the correct Result.

var foo = {    hasownproperty:function () {        return false;    },    bar: ' Here is Dragons '};foo.hasownproperty (' Bar '); Always return false//using the {} object's hasownproperty and set it down to Foo{}.hasownproperty.call (foo, ' bar '); True


hasOwnProperty is the only available method when checking for the existence of an attribute on an object. At the same time when iterating through an object using the for in Loop. It is recommended to always use the hasOwnProperty method. This avoids the interference caused by the prototype object extension, so let's take a look at the sample:

Change Object.prototypeObject.prototype.bar = 1;var foo = {moo:2};for (var i in Foo) {    console.log (i);//output two properties: bar and Moo


We can't change the behavior of the for-in statement, so we can only use the hasOwnProperty method if we want to filter the Results. The code is as Follows:


The code for this version number is the only correct Notation. Because we used the hasownproperty, this time we just output moo.

Assuming that hasOwnProperty is not used, This code may go wrong when the native object prototype (for example, Object.prototype) is Extended.

Summary: It is recommended to use Hasownproperty. Do not do whatever the code does for the environment, if not, if the native object has already been Expanded.

JavaScript quest: powerful prototypes and prototype chains

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.