js继承实现之Object.create

同事前几天去面试,回来同步了一下面试题库,其中一道题就是”new和Object.create的区别”。听到这个题目,个人第一个反映是 , what?( ⸝⸝⸝°_°⸝⸝⸝ ), Object.create这个东东我没有用过,怎么回答。为了不没法给出response的尴尬,老夫抓紧一切时间开始在console里演示着。面试

-> demo <-函数

function Person(name, sex) {
   this.name = name;
   this.sex = sex;
}
Person.prototype.getInfo = function() {
   console.log('getInfo: [name:' + this.name + ', sex:' + this.sex + ']');
}
var a = new Person('jojo', 'femal');
var b = Object.create(Person.prototype);

图片描述

-> 分析 <-学习

赤裸裸的结果,a就是对象Person的实例,a.__proto__ === Person.prototype。what about b ? b是对象F的一个实例,而且b.__proto__ === Person.prototype的。this

这个F究竟是个啥呢? 好了,又到了copy-paste时间了,参考了https://developer.mozilla.org... 其实现的polyfill方法:spa

if (typeof Object.create !== "function") {
    //此方法未考虑create的第二个参数的实现
    Object.create = function (proto, propertiesObject) {
        if (typeof proto !== 'object' && typeof proto !== 'function') {
            throw new TypeError('Object prototype may only be an Object: ' + proto);
        } else if (proto === null) {
            throw new Error("This browser's implementation of Object.create is a shim and doesn't support 'null' as the first argument.");
        }

        if (typeof propertiesObject != 'undefined') throw new Error("This browser's implementation of Object.create is a shim and doesn't support a second argument.");
        //实现一个隐藏函数
        function F() {}
        //函数的原型设置为参数传进来的原型
        F.prototype = proto;
        // 返回一个F函数的实例,即此实例的__proto__指向为参数proto
        return new F();
    };
}

好吧,既然都看了polyfill了,就知道Object.create究竟是干啥的了,它就是生成了一个实例,这个实例的原型由我来指定,可是它的构造函数F被隐藏了。那下面咱们来验证一下是否是这个逻辑。prototype

图片描述

经过Object.create()生成的实例怎么才能有本身的属性呢,别怕,咱们看一下它完成的面目是怎样的,撒花,揭幕~~Object.create(proto, [propertiesObject]), 人家是有第二个参数滴。能够本身定义它的属性,可写、可配、可枚举,都可本身定义,实现一条龙自助服务。3d

var b = Object.create(Person.prototype, {
    name: {
        value: 'coco',
        writable: true,
        configurable: true,
        enumerable: true,
    },
    sex: {
        enumerable: true,
        get: function(){ return 'hello sex'},
        set: function(val){console.log('set value:' + val)}
    }
})

-> 更进一步 <-code

说了这么多,那Object.create的应用价值究竟是什么呢? 看一下本文标题就知道了,固然说的是继承了,操刀试一下。对象

function Student(name, sex, age) {
    Person.call(this, name, sex);
    this.age = age;
}
//原型链拼接
Student.prototype = Object.create(Person.prototype);
//构造函数弯了,纠正
Student.prototype.constructor = Student;
Student.prototype.getInfo = function() {
    console.log('getInfo: [name:' + this.name + ', sex:' + this.sex + ', age:' +this.age + '].');
}
    
var s = new Student('coco', 'femal', 25);

图片描述

s是Student的实例,Person.prototype在s的原型链上,而且这个F实例的constructor又指回了Student。
既然说到了这里,那若是想要一个对象继承多个类怎么办呢?在上面的代码基础上使用mixin加工下就可啦。blog

//再建立一个基类
function Animal(age) {
 this.age = age;
}
Animal.prototype.say = function(language) { 
    console.log('you say ' + language);
}

function Student(name, sex, age) {
    Person.call(this, name, sex);
    Animal.call(this, age);
}
//原型链拼接
Student.prototype = Object.create(Person.prototype);
Object.assign(Student.prototype, Animal.prototype);
Student.prototype.constructor = Student;
Student.prototype.getInfo = function() {
    console.log('getInfo: [name:' + this.name + ', sex:' + this.sex + ', age:' +this.age + '].');
};
var s = new Student('coco', 'femal', 25);

s的原型还是一个F实例,其原型指向了Person,可是这个F实例上mixin了Animal的方法。可是原型链上并无Animal什么事,经过instanceof能够验证这一点。这种方式比较适合父类为同级别,子类只要拥有相同的属性和方法便可的状况。

图片描述

若有异议处,欢迎你们指出来,一块儿探讨。学习费脑掉了好多头皮屑,不过今天又能够碎个觉了。

∧__∧( ●ω●) |つ/(___/└-(____/bug>>>bug>>bug>bug  ̄ ̄ ̄ ̄ ̄ ̄

相关文章
相关标签/搜索