JS中prototype的自我总结(new、function、object等)

1,678 阅读4分钟

前言

说明:内容总结自王福朋等多位的文章

181637013624694.png

我感觉理解原型的核心就是这张图片;

理解构造函数和原型对象和实例的三角恋

构造函数通过new生成实例,实例通过.constructor找到构造函数,构造函数通过.prototype找到其的原型对象(默认值就是一个对象,含有一个constructor的属性指向构造函数),原型对象通过.constructor属性指向构造函数;另外一条就是实例通过__proto__找到原型对象(隐藏属性即暗恋);

原型链

原型链就是当你访问对象的属性时,如果不存在这个属性就会向其原型对象找这个属性,直至Object.prototype.__proto__都找不到就返回null;万物都是对象,所以对象的原型对象就是原型链的终点;

原型继承

主要介绍的是基于原型关系的继承写法,首先继承主要的目的就是想让子代能够使用父代的东西,感觉就是像子承父业,既然是继承,子与父必然是同一个类型,这边就先讨论构造函数;原型中原型链就满足了继承的所需,所以原型继承就是将两个构造函数组成原型链;

// 1. 父构造函数
function Father(uname, age) {
    // this 指向父构造函数的对象实例
    this.uname = uname;
    this.age = age;
}

Father.prototype.money = function() {
    console.log(100000);
};

// 2 .子构造函数
function Son(uname, age, score) {
    // this 指向子构造函数的对象实例
    //如果要使用父构造函数的构造就加Father.call(this, uname, age);
    Father.call(this, uname, age);
    this.score = score;
}

// Son.prototype = Father.prototype; 这样直接赋值会有问题,如果修改了子原型对象,父原型对象也会跟着一起变化

Son.prototype = new Father();
// 如果利用对象的形式修改了原型对象,别忘了利用constructor 指回原来的构造函数 目的是形成完美的原型对象链,否则Son.prototype.constructor指向的就是Father
Son.prototype.constructor = Son;

// 这个是子构造函数专门的方法
Son.prototype.exam = function() {
console.log('孩子要考试');
}
var son = new Son('洵回', 18, 100);
console.log(son);

son因为Father.call(this, uname, age)在构造的时候能够使用父的相关构造;Son.prototype = new Father();因为这个son可以使用父的.money,为了避免调用等问题在增加Son.prototype.constructor = Son;详情看阮一峰的相关内容;

理解 Object 和 Function 这个闭环的关系

我感觉Object和Function的关系有点类似鸡和蛋的关系,主要就是 Object.__proto__ 指向 Function.prototype,而 Function.prototype.__proto__指向的是Object.prototype;不过从结果来看prototype,Function构建出来的实例都具有prototype这个属性,而Object构建出来的实例都有 __proto__这个属性,JS中又基本都是对象,所以基本都有__proto__这个属性

这就解释了我之前的一个疑惑,为什么Object构建出来的实例不具有prototype,而function构建出来都具有prototype;

理解new的操作

new过程中会新建对象,此对象会继承构造器的原型与原型上的属性,最后它会被作为实例返回这样一个过程;

  • 以构造器的prototype属性为原型,创建新对象;
  • 将this(也就是上一句中的新对象)和调用参数传给构造器,执行;
  • 如果构造器没有手动返回对象,则返回第一步创建的新对象,如果有,则舍弃掉第一步创建的新对象,返回手动return的对象。

可以这样写相关的代码

//自己定义的new方法
let newMethod = function (Parent, ...rest) {
    // 1.以构造器的prototype属性为原型,创建新对象;
    let child = Object.create(Parent.prototype);
    // 2.将this和调用参数传给构造器执行
    let result = Parent.apply(child, rest);
    // 3.如果构造器没有手动返回对象,则返回第一步的对象
    return typeof result  === 'object' ? result : child;
};

或者是按照你不知道的js上说得:

new调用:

  • 1)创建或构造一个新的对象,
  • 2)新对象被执行【【原型】】连接
  • 3)新对象会绑定到函数调用的this
  • 4)若函数没有返回其他对象,则new表达式中函数会自动返回这个新对象

也就是

function createnew(person,...rest){
    let obj = new Obejct();
    obj.__proto__=person.prototype;
    let result = person.call(obj,...rest);
    return typeof result ==='object'? result : obj
}

以上就是我的总结,有问题希望指出让我学习学习;