0

I know javascript prototype inheritance pretty well but I have a situation similar to angular scopes and I don't know how to handle it.

Let's begin with wrong (because it is bad idea to change __proto__ property) but working example

https://jsfiddle.net/hxm61r7j/

function Scope() {
}

Scope.prototype.$new = function() {
    var new_scope = new Scope();

    //TODO: change line bellow 
    new_scope.__proto__ = this;

    return new_scope;
}

// Create root scope
var scope_level_1 = new Scope();
scope_level_1.a = 'scope_level_1 a';
scope_level_1.b = 'scope_level_1 b';

// Create scope which inherits from parent
var scope_level_2 = scope_level_1.$new();
scope_level_2.b = 'scope_level_2 b';

// We don't have property "a" in "scope_level_2" so it will be taken from "scope_level_1"
// But we have property "b" in "scope_level_2" so it will be taken from there
console.log(scope_level_2.a, scope_level_2.b);

As you see I need a way to create some kind of scope which will have some properties. Later I need to create other scope which will inherit from previous one. I mean if property is not defined in current scope it will be taken from parent one.

But I'm not sure how to change this line: new_scope.__proto__ = this;

Arūnas Smaliukas
  • 3,231
  • 6
  • 27
  • 46
  • possible duplicate of [How does JavaScript .prototype work?](http://stackoverflow.com/questions/572897/how-does-javascript-prototype-work) – Robert Rossmann Jun 01 '15 at 14:09
  • @RobertRossmann It is not this case. I know how to use `prototype` in usual cases. For example if I need to have constructor `Vehicle` and two other constructors `Car` and `Motorbike` and they both inherits from `Vehicle`. But in this case I need only one constructor `Scope` which inherits from itself – Arūnas Smaliukas Jun 01 '15 at 14:22
  • Inheriting from itself will not help achieve anything - any property which exists on `Scope` would be immediately resolved on current object and everything else will be unresolvable (i.e. `undefined`) at best; at worst, the engine will reach maximum stack trace while trying to recursively find your property. What is your use case for such behaviour...? – Robert Rossmann Jun 01 '15 at 14:27
  • I think I got it... Posting answer shortly. – Robert Rossmann Jun 01 '15 at 14:31
  • I hope you got it @RobertRossmann :) Note that example is working and I think it describes what is my case. I just don't like that I change `__proto__` property directly – Arūnas Smaliukas Jun 01 '15 at 14:33

2 Answers2

1

I think you are looking for Object.create().

This function allows you to create a new JavaScript object with the internal prototype property (__proto__) set to whatever object you pass to the function as first argument:

Scope.prototype.$new = function() {
    var new_scope = Object.create(this);
    // If you also need to call the constructor function:
    Scope.call(new_scope);

    return new_scope;
}

Alternatively, you can use Object.setPrototypeOf(), but this is part of ECMAScript 6 and browser support may vary:

Scope.prototype.$new = function() {
    var new_scope = new Scope();

    Object.setPrototypeOf(new_scope, this);

    return new_scope;
}

Note that the __proto__ property has only been standardised in ES 6 and its direct manipulation is therefore discouraged.

Robert Rossmann
  • 11,931
  • 4
  • 42
  • 73
1

First of it is not a good practice to use dunder proto , there is setPrototyOf for that cause

setPrototypeOf

Unless of course you need to support the older IE versions.

Now remember that after setting teh prototype you ALSO need to set the constructor again. So the correct would be new_scope.proto = this.prototype; new_scope.proto.constructor=this.prototype.constructor

Dan Kuida
  • 1,017
  • 10
  • 18
  • 1
    a good explanation available in http://shop.oreilly.com/product/0636920033738.do – Dan Kuida Jun 01 '15 at 14:47
  • Thanks for the answer. (@Robert first posted so I accepted his answer). And many thanks for a book. I love reading books! – Arūnas Smaliukas Jun 01 '15 at 14:59
  • But why is it bad practice to use this? I think `angularjs` does it in similar way, and I love that I can access variables from parent scope. My case is exactly the same – Arūnas Smaliukas Jun 01 '15 at 15:01
  • Bad practice is **changing** prototypes of **existing objects**; there's nothing wrong with creating objects with custom prototypes. It can break optimisations. – Robert Rossmann Jun 01 '15 at 15:04