Why declare properties on the prototype for instance variables in JavaScript

后端 未结 4 1852
清酒与你
清酒与你 2020-12-12 21:13

I\'m trying to get my head around this black art called JavaScript - and, I must admit, pretty excited about it. I\'ve been looking at code examples, mainly from \"easeljs\"

相关标签:
4条回答
  • The value on a prototype has a key behaviour that is different from a property set directly on the instance. Try this:

    // Create a constructor
    function A() {}
    
    // Add a prototype property
    A.prototype.name = "Freddy";
    
    // Create two object instances from
    // the constructor
    var a = new A();
    var b = new A();
    
    // Both instances have the property
    // that we created on the prototype
    console.log(a.name); // Freddy
    console.log(b.name); // Freddy
    
    // Now change the property on the
    // prototype
    A.prototype.name = "George";
    
    // Both instances inherit the change.
    // Really they are just reading the
    // same property from the prototype
    // rather than their own property
    console.log(a.name); // George
    console.log(b.name); // George
    

    This would not possible without prototypical inheritance.

    You can test whether the property is the instances property or the prototype property using the hasOwnProperty method.

    console.log(a.hasOwnProperty("name")); // false
    

    An instance can override the prototype value.

    b.name = "Chris";
    console.log(b.hasOwnProperty("name")); // true
    console.log(a.name); // George
    console.log(b.name); // Chris
    

    And return to the prototype value.

    delete b.name;
    console.log(b.hasOwnProperty("name")); // false
    console.log(b.name); // George
    

    This is a powerful part of prototypical inheritance.

    In the other pattern:

    function A() {
      this.name = "George";
    }
    

    The this.name variable is declared again with every new instance.

    It makes some sense to have methods as functions declared on the prototype. Rather than the function definition being re-declared on every instance, all instances can share a single function.

    In terms of variables, rather than functions, the prototype can possibly be used for default values in the case that an instance does not set its own value.

    The code in a fiddle

    0 讨论(0)
  • 2020-12-12 21:31

    Other answers have already explained the difference between prototype vs instance properties.

    But just to add to the answer, let's break down your code snippet:

    (function(){                         // <------- 1
       // constructor
       function MyCircle(radius){        // <------- 2
           this.radius = radius;         // <------- 2.1
       }
       MyCircle.prototype.radius;        // <------- 3
       this.area = function(){           // <------- 4
           return 3.14*this.radius*this.radius;
       };
       window.MyCircle = MyCircle;       // <------- 5
    }());
    
    1. Creating an IIFE which acts as a scope container for the inner code
    2. Declaring a function called MyCircle using a constructor pattern (but observe that it never gets "constructed" so should probably get rid of the capital letter since it's misleading)
      • when invoked creates a radius instance property on the invoked object
    3. Attempting to access a radius property on MyCircle function's prototype which doesn't exist so evaluates to undefined
    4. Creating an area instance property on the global window object and assigning it a function expression
    5. Creating a MyCircle instance property on a window object and assigning to it the MyCircle function

    Summary: It seems like it's creating an area and MyCircle properties on the global window object, and when MyCircle is invoked it creates an additional radius property.

    Usage: MyCircle should be invoked before area since area relies on MyCircle initialising the radius:

    window.MyCircle(10);
    window.area(); // evaluates to 314
    
    0 讨论(0)
  • 2020-12-12 21:46

    A value stored on the prototype provides a default value for that property.

    If you subsequently write a value to that property, the instance will acquire that new value, hiding the value that's on the prototype, which will be left intact.

    In the context of the code you've now added to the question:

    MyCircle.prototype.radius;
    

    does absolutely nothing. It's a no-op - it attempts to read that property and then discards the result.

    0 讨论(0)
  • 2020-12-12 21:51

    Yeah, I agree the prototype can be used for default values of properties (variables). The constructor function doesn't need to declare a property; it may be done conditionally.

    function Person( name, age ) {
        this.name = name;
    
        if ( age ) {
            this.age = age;
        }
    }
    
    Person.prototype.sayHello = function() {
        console.log( 'My name is ' + this.name + '.' );
    };
    
    Person.prototype.sayAge = function() {
        if ( this.age ) {
            console.log( 'I am ' + this.age + ' yrs old!' ); 
        } else {
            console.log( 'I do not know my age!' );
        }
    };
    
    Person.prototype.age = 0.7;
    
    //-----------
    
    var person = new Person( 'Lucy' );
    console.log( 'person.name', person.name ); // Lucy
    console.log( 'person.age', person.age );   // 0.7
    person.sayAge();                           // I am 0.7 yrs old!
    

    See how Lucy's age is conditionally declared and initialized.

    0 讨论(0)
提交回复
热议问题