Search code examples
javascriptinheritancescope-chain

Javascript scope chaining inheritance


I am a student studying programming.

I have a question.

function a () {

}

a.prototype.prtSomething = function(arg) { console.log(arg); }

function b () {

}

var myObj = new b();

If I want to use the method of a in myObj, we use this code.

b.prototype = Object.create(a.prototype);
b.prototype.constructor = b;

That means changing the target of scope chaining. But why don't we use this code?

b.prototype.__proto__ = a.prototype;

I think there must be a reason to creating and using a new object. but I don't know. Please teach me. Thank you.


Solution

  • But why don't we use this code?

    You could, and it would work, but:

    1. Changing an object's prototype is generally not a good idea and may make JavaScript engines not optimize that object as well.

    2. __proto__ used to be non-standard (and still is outside of web browsers) and until ES2015 there was no standard way to change an object's prototype. ES2015 added Object.setPrototypeOf (and added __proto__ to its web-only Annex B).

    So rather than changing the prototype of b.prototype, typically we used to replace it instead.

    (I say "used to" because I wouldn't write that code in modern JavaScript, I'd use class syntax if I wanted an inheritance hierarchy of constructor functions.)


    Side note: Don't use __proto__. It's purely there for backward compatibility with old code, is not specified for JavaScript outside of browsers, and isn't present on objects that don't inherit from Object.prototype. (For instance, if you do const x = Object.create(null);, then "__proto__" in x is false and assigning to x.__proto__ won't change its prototype.)

    Instead, if you have a reason to change the prototype of an object, use Object.setPrototypeOf:

    function A() {
    }
    
    A.prototype.prtSomething = function(arg) {
        console.log(arg);
    };
    
    function B() {
    }
    Object.setPrototypeOf(B.prototype, A.prototype);
    
    const myObj = new B();
    myObj.prtSomething("x");

    Also note that I've changed a to A and b to B to conform with standard JavaScript naming (constructor functions start with a capital letter).