JS原型链

作者: wyc0859 | 来源:发表于2022-03-12 01:27 被阅读0次

JS函数有双重性质:new实例时是类型,直接获取属性时是对象(如:son.name)
JS函数为对象时,有3属性prototype__proto__,自己定义的静态属性和方法(多个),不存在自身属性
JS函数的原型链就一个,不分是对象时还是类型时

未命名文件 (3).png
function parent(name) {
  let funName = "变量name";
}
parent.staticName = "我叫A";
parent.staticAge = "最少21岁";
parent.prototype.wife = "父亲的女人";

function son(name) {
  this.info = "son属性";
  this.name = name;
}
son.prototype.girl = "儿子的女朋友";

console.log("自身属性:", parent.funName); //undefined 不存在自身属性
console.log("静态属性:", parent.staticName); //我叫A
console.log("prototype:", parent.prototype); //{wife: '父亲的女人', constructor: ƒ} constructor包含了静态属性staticName
console.log("1:", parent.prototype.prototype); //undefined
console.log("__proto__:", parent.__proto__); //对象祖先类:ƒ () { [native code] }
console.log("prototype.__proto__:", parent.prototype.__proto__);
//{constructor: ƒ, __defineGetter__: ƒ, __defineSetter__: ƒ,...}
image.png

proto代表上一层对象空间
对象空间上的__proto__可以修改
原型空间上的__proto__也可以修改

console.log("parent.__proto__:", parent.__proto__); //ƒ () { [native code] }
parent.__proto__ = {};
console.log("parent.__proto__-edit:", parent.__proto__); //{}
parent.__proto__ = [];
console.log("parent.__proto__-edit:", parent.__proto__); //[]

//原型空间上的__proto__也可以修改
console.log("parent.prototype.__proto__-1:", parent.prototype.__proto__);
//{constructor: ƒ, __defineGetter__: ƒ, __defineSetter__: ƒ, ...}
parent.prototype.__proto__ = {};
console.log("parent.prototype.__proto__-2:", parent.prototype.__proto__); //{}

//无限循环
console.log("parent:", parent); //parent的对象空间
console.log("parent:", parent.prototype); //parent的原型空间
console.log("parent:", parent.prototype.constructor); //parent的对象空间
console.log("parent:", parent.prototype.constructor.prototype); //parent的原型空间

继承

简单继承

可以看出,小A继承了实例上的funName,和原型上的 wife
但一个实例不能获取静态属性,也不能继承静态属性。静态属性 == 类属性

const LaoA = new parent("老A");
const XiaoA = new son("小A");
XiaoA.__proto__ = LaoA;

console.log("小A:", XiaoA, XiaoA.funName, XiaoA.wife);
//son {info: 'son属性', name: '小A'} 老A 父亲的女人 
console.log("小A-静态属性:", XiaoA.staticAge); //undefined  

中等继承

继承后,操作属性或方法,会一层层向上查找,但到原型空间查找时,原型空间有(constructor.prototype和__proto__
这时只走constructor.prototype 这条线去查找,所以找不到爷爷的job
但通过原型链是能找到爷爷类的

function grandfather() {}
grandfather.staticCar="奔驰"
grandfather.prototype.job = "老师";

parent.__proto__ = grandfather; //将父类的__proto__指向爷爷类
console.log("小A调用parent的对象空间:", XiaoA.__proto__.__proto__.constructor); //parent的对象空间
console.log(
  "小A调用parent的上层空间:",
  XiaoA.__proto__.__proto__.constructor.__proto__
); //grandfather
console.log("小A-获取爷爷的job:", XiaoA.job); //undefined
实例获取属性走的路线

子类继承静态属性

方法一:找到父亲爷爷的静态属性,然后手动赋值给 子类静态属性

console.log("son获取静态属性:", son.staticName); //undefined

//下面循环,打印出了3个静态属性和方法
// for (let key in parent) {
//   console.log("key:", key); //key:staticName, key:staticAge, key:staticCar
// }
for (let key in parent) {
  //只要本构造函数的自有属性
  if (Object.prototype.hasOwnProperty.call(parent, key)) {
    //console.log("v:", key); //key:staticName, key:staticAge
    son[key] = parent[key]; //好比son.staticX="abc" 直接写静态属性
  }
}
console.log("son获取静态属性2:", son.staticName); //我叫A   
获取静态属性走的路线

方法二:parent之所以能获取爷爷的静态属性,是因为在前面执行了这段代码

parent.__proto__ = grandfather  //将父类的__proto__指向爷爷类

那么直接把

son.__proto__ = parent  

就搞定了,一样的道理。

方法三: (ES6方式) 用Object.setPrototypeOf()

Object.setPrototypeOf(parent, grandfather)
这行代码最终建立的关系,还是son.__proto__ = parent

孙子获取静态属性路线

之所以列举3种方式,是因为浏览器有的使用es5,有的es6,考虑到兼容。
不然直接Object.setPrototypeOf()搞定。但梳理了一遍,也就更清楚原型链是如何继承的,并继承静态属性和方法


结尾:

抛开 JavaScript 用于模拟 Java 类的复杂语法设施(如 new、Function Object、函数的 prototype 属性等)
原型系统可以说相当简单,可以用两条概括:

1、如果所有对象都有私有字段[[prototype]],就是对象的原型;
2、读一个属性,如果对象本身没有,则会继续访问对象的原型,直到原型为空或者找到为止。

这个模型在 ES 的各个历史版本中并没有很大改变
ES6 提供了一系列内置函数,以便更为直接地访问操纵原型。
分别为:
Object.create 根据指定的原型创建新对象,原型可以是 null;
Object.getPrototypeOf 获得一个对象的原型;
Object.setPrototypeOf 设置一个对象的原型。

相关文章

  • 廖雪峰JS小记

    (function(){})() 原型,原型链 浅谈Js原型的理解JS 原型与原型链终极详解 对象 对象:一种无序...

  • JS的__proto__和prototype

    最近在回顾JS的原型和原型链的知识,熟悉JS的同学都知道JS的继承是靠原型链实现的,那跟原型链相关的属性__pro...

  • Javascript(三)之原型继承理解

    进阶路线 3 原型继承 3.1 优秀文章 最详尽的 JS 原型与原型链终极详解 一 最详尽的 JS 原型与原型链终...

  • 从实现角度分析js原型链

    从实现角度分析js原型链 欢迎来我的博客阅读:《从实现角度分析js原型链》 网上介绍原型链的优质文章已经有很多了,...

  • JS原型链

    1什么是JS原型链? 通过__proto__属性将对象与原型对象进行连接. 1.1 JS原型链的作用? 组成的一个...

  • 关于JS中的原型和原型链

    目录 关于js 对象和原型 原型链 基于原型链的继承 参考资料ECMAScript 6 入门JavaScript原...

  • js_继承及原型链等(四)

    js_继承及原型链等(三) 1. 继承 依赖于原型链来完成的继承 发生在对象与对象之间 原型链,如下: ==原型链...

  • 2022前端高频面试题

    JS相关 1.原型和原型链是什么 原型和原型链都是来源于对象而服务于对象的概念js中引用类型都是对象,对象就是属性...

  • JavaScript原型链

    js原型链 原型链是JS面向对象的基础非常重要 所有对象只有__proto__属性,而函数具有prototype属...

  • web前端面试之js继承与原型链(码动未来)

    web前端面试之js继承与原型链(码动未来) 3.2.1、JavaScript原型,原型链 ? 有什么特点? 每个...

网友评论

    本文标题:JS原型链

    本文链接:https://www.haomeiwen.com/subject/iumhdrtx.html