js 基础复习: proto & prototype, 温故而知新.

ES5 继承

20160314212504_39150

function Super() {}

function Sub() {}
Sub.prototype = new Super();
Sub.prototype.constructor = Sub;

var sub = new Sub();

console.assert(Sub.prototype.constructor === Sub) // ② true
console.assert(sub.constructor === Sub); // ④ true
console.assert(sub.__proto__ === Sub.prototype); // ⑤ true
console.assert(Sub.__proto__ !== Super
               && Sub.__proto__ === Object.__proto__); // ⑥ true this is different from ES6
console.assert(Sub.prototype.__proto__ == Super.prototype); // ⑦ true
console.assert(Sub.prototype instanceof Super);
console.assert(Object.getPrototypeOf(Sub) !== Super
               && Object.getPrototypeOf(Sub) === Object.__proto__); // this is different from ES6

ES6 继承

20160116201909_44777

class Super {}

class Sub extends Super {}

var sub = new Sub();

// sub is an empty object has no properties but object properties included `__proto__`, `constructor` and so on.

console.assert(Sub.prototype.constructor === Sub); // ② true
console.assert(sub.constructor === Sub); // ④ true
console.assert(sub.__proto__ === Sub.prototype); // ⑤ true
console.assert(Sub.__proto__ === Super); // ⑥ true this is different from ES5
console.assert(Sub.prototype.__proto__ === Super.prototype); // ⑦ true
console.assert(Sub.prototype instanceof Super);
console.assert(Object.getPrototypeOf(Sub) === Super); // this is different from ES5

Array 继承方式 ( ES5 extends Example )

// Array ---> Object ---> null
console.assert(Array.prototype.constructor === Array);
console.assert([].constructor === Array);
console.assert([].__proto__ === Array.prototype);
console.assert(Array.__proto__ !== Object && Array.__proto__ === Object.__proto__);
console.assert(Array.prototype.__proto__ === Object.prototype);
console.assert(Array.prototype instanceof Object);
console.assert(Object.getPrototypeOf(Array) !== Object && Object.getPrototypeOf(Array) === Object.__proto__);

HTMLElement ( ES6 extends Example )

// HTMLImageElement ---> HTMLElement ---> xxx
var img = new Image();
console.assert(HTMLImageElement.prototype.constructor === HTMLImageElement);
console.assert(img.constructor === HTMLImageElement);
console.assert(img.__proto__ === HTMLImageElement.prototype);
console.assert(HTMLImageElement.__proto__ === HTMLElement);
console.assert(HTMLImageElement.prototype.__proto__ === HTMLElement.prototype);
console.assert(HTMLImageElement.prototype instanceof HTMLElement);
console.assert(Object.getPrototypeOf(HTMLImageElement) === HTMLElement);

new operator

var o = new Foo();
// is equal to
var o = new Object();
o.__proto__ = Foo.prototype;
Foo.call(o);

Hack new operator

function new(clazz) {
    var o = new Object();
    o.__proto__ = Clazz.prototype;
    Clazz.call(o);
    return o;
}

Babel loose mode

Enable babel loose will effects HTMLDivElement.__proto__ === HTMLElement

The answer is NO. See babel source code

Conclusion

How to detect whether a Sub-Class inherits a Super-Class whitout new Sub-Class ?

ES5 Syntax

  • Sub.prototype.__proto__ === Super.prototype
  • Sub.prototype instanceof Super

ES6 Syntax (or Babel)

  • Sub.prototype.__proto__ === Super.prototype
  • Sub.prototype instanceof Super
  • Sub.__proto__ === Super
  • Object.getPrototypeOf(Sub) === Super

References