前端重新开始 -- 对象与原型

222 阅读1分钟

文章主要有两个目的:

  • 理解javascript的prototype 与 proto
  • 理解javascript的继承

参考Mdn-继承与原型链

proto 与 prototype

proto

  • 除了null/null之外的变量都有__proto__属性;
  • proto 能够直接访问;
var p = { sayGoodBuy: function(){ console.log('buybuy'); }, 
}
undefined
var s = {
}
undefined
s.__proto__
//{constructor: ƒ, __defineGetter__: ƒ, __defineSetter__: ƒ, hasOwnProperty: ƒ, __lookupGetter__: ƒ, …}
Object.setPrototypeOf(s,p)
{}__proto__: sayGoodBuy: ƒ ()__proto__: Object
s.__proto__
//{sayGoodBuy: ƒ}

prototype:

  • Funcion中定义;
  • 在new 实例化后的对象的__proto__;
var Person = function(name,age){
    this.name = name;
    this.age = age;
}

Person.prototype = {
    constructor : Person.prototype.constructor,
    sayHi: function(){
        console.log(`hi, i am ${this.name}`);
    }
}
{constructor: ƒ, sayHi: ƒ}
var p = new Person('sfg',32);
p.__proto__ === Person.prototype
//true
p.sayHi()
//VM5858:4 hi, i am sfg

我们的new 其实是做了什么事情的?抄别人的面向对象和原型——永不过时的话题

  1. 首先创建一个空对象,这个对象将会作为执行 new 构造函数() 之后,返回的对象实例
  2. 将上面创建的空对象的原型(proto),指向构造函数的 prototype 属性
  3. 将这个空对象赋值给构造函数内部的 this,并执行构造函数逻辑
  4. 根据构造函数执行逻辑,返回第一步创建的对象或者构造函数的显式返回值;
var newFunction = function(){
    const target = Array.prototype.slice.call(arguments,0,1)[0],
          args = Array.prototype.slice.call(arguments,1); 
    let obj = Object.setPrototypeOf({},Object.create(target.prototype)); 
    let result = target.apply(obj,args);
    if(result && typeof(result) === 'object'){
        return result;
    }
    return obj;
}

实现继承,抄别人的面向对象和原型——永不过时的话题

  • 原型链继承
Child.prototype = new Parent()
  • 构造方法继承
function Child (args) {
    // ...
    Parent.call(this, args)
}
  • 组合继承
function Child (args1, args2) {
    // ...
    this.args2 = args2
    Parent.call(this, args1)
}
Child.prototype = new Parent()
Child.prototype.constrcutor = Child
  • 一个比较完整的继承

完整的继承所需要的步骤:

  1. 修复prototype
  2. 修复constructor
  3. 修复超类
  4. 继承静态参数
var inh = function(s,p){
    s.prototype = Object.create(p.prototype);
    s.prototype.constructor = s;
    s.super = s;
    if(Object.setPrototypeOf){
        Object.setPrototypeOf(s,p);
    }else if(s.__proto__){
        s.__proto__ = p;
    }
}