Skip to content

you dont know about js

objects

We end up with two objects, linked to each other. That's it. We didn't instantiate a class. We certainly didn't do any copying of behavior from a "class" into a concrete object. We just caused two objects to be linked to each other.

In fact, the secret, which eludes most JS developers, is that the new Foo() function calling had really almost nothing direct to do with the process of creating the link. It was sort of an accidental side-effect. new Foo() is an indirect, round-about way to end up with what we want: a new object linked to another object.

Can we get what we want in a more direct way? Yes! The hero is Object.create(..)

how it seems like a.constructor === Foo being true means that a has an actual .constructor property on it, pointing at Foo? Not correct.

This is just unfortunate confusion. In actuality, the .constructor reference is also delegated up to Foo.prototype, which happens to, by default, have a .constructor that points at Foo.

image-20230223152551919

The important part is Bar.prototype = Object.create( Foo.prototype ). Object.create(..) creates a "new" object out of thin air, and links that new object's internal [[Prototype]] to the object you specify (Foo.prototype in this case).

In other words, that line says: "make a new 'Bar dot prototype' object that's linked to 'Foo dot prototype'."

× Bar.prototype = Foo.prototype 这样Bar.prototype上做的任何修改都会影响到Foo的实例化对象了

× Bar.prototype = new Foo() 作用上可以达到,但是new Foo()的过程中可能带来side effects

※ 用es6写继续的话 Object.setPrototypeOf( Bar.prototype, Foo.prototype );

check if two objs are related:

image-20230223155659252

Or Foo.prototype.isPrototypeOf(a) // true

__proto__的实现:

image-20230223155832593

Object.create很厉害!它直接联系了两个对象而不需要通过构造函数来中介!相当于:

if(!Object.create){
  Object.create = function(o) {
    function F(){}
    F.prototype = o;
  }
}

继承相关

这里是一份编译出来的范本:

复杂版:给Object.setPrototypeOf和Object.create加了polyfill

var extendStatics = function(d, b) {
    extendStatics = Object.setPrototypeOf ||
                ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
                function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
    return extendStatics(d, b);
};
function __extends(d, b) {
    extendStatics(d, b);
    function __() { this.constructor = d; }
    d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
}

简要版:

function __extends(d, b) {
    Object.setPrototypeOf(d, b);
    d.prototype = Object.create(b); //我在想 这一行的目的不会和上一行重复吗?..hui'de
}

---------------使用------------------
var MNode = /** @class */ (function (_super) {
__extends(MNode, _super);
function MNode(options) {
    var _this = _super.call(this, options) || this;
}
MNode.prototype.xx = function(){
    _super.prototype.xx.call(this); // 因为可能会覆盖父构造函数里的方法 所以需要手动调用
}
)(Events)

Object.create() vs Object.setPrototypeOf()

前者es6一般也这么用呀:A.prototype = Object.create(B.prototype)

后者也是一样的 Object.setPrototypeOf(B.prototype, A.prototype)

image-20230223161344870

hah mdn上都说实现上实际是性能比较慢的

所以 Object.create(B.prototype)优于Object.setPrototypeOf(B.prototype, A.prototype)!!

混入:

function MyClass() {
  SuperClass.call(this);
  OtherSuperClass.call(this);
}
// 集成一个类
MyClass.prototype = Object.create(SuperClass.prototype);
// 混合其他
Object.assign(MyClass.prototype, OtherSuperClass.prototype);
// 重新指定 constructor
MyClass.prototype.constructor = MyClass;
MyClass.prototype.myMethod = function() {
  // do a thing
}