JavaScript 面向对象(七)原型链深入
来源:互联网 发布:自动化控制软件 编辑:程序博客网 时间:2024/06/04 13:47
7.1 __proto__属性
W3C是没有规定一个元素的原型链有一个可见的属性,Chrome浏览器特有 __proto__属性。实际上,其他浏览器有原型链的机制,但是我们看不见这个属性。只不过,Chrome浏览器为了我们初学者学习方便,增加了这个属性:
但是在Chrome中,__proto__属性是可以自由更改的,而这根本不是语言的规范,其他浏览器没有实现,也就是说,__proto__属性在其他浏览器中,在语言规范中根本就是看不见的,就没有这个属性。
原型链的获得有两种情况:
1)引用类型值的对象它们的字面量的__proto__就是他们类型的构造函数的prototype。
2)通过new关键字,此时构造函数的prototype就是实例的__proto__。
实际上,在语言规范中,一旦原型链产生,将不能更改!只不过Chrome浏览器做的高级了一些,让我们自由更改__proto__而已。
ECMAScript2016中,提供了Object.create()函数,可以让我们指定一个对象为原型对象,来创建新对象。
这个Object.create 兼容性很差,我们能不能自己写一个函数create,它接受一个对象参数,返回以这个对象为原型对象的新对象。我们可以用一个临时的构造函数来中转:
显而易见的是,任何一个对象都有原型对象,原型链的终点就是Object.prototype
在Chrome中,可以自由设置__proto__,从而可以让一个对象的原型对象不存在。
对象的toString()方法都是定义在Object.prototype上的,而这个对象是所有对象的原型链终点,所以任何对象都能调用toString()方法,但是切断原型链之后就不行了。
事实上,在语言设计中,当对象一旦创建,原型链一旦确定,此时就没有任何方法删除、改变对象的原型链。Chrome中的__proto__仅仅供研究、学习使用。
7.2 constructor属性
任何一个构造函数的prototype身上,都有一个constructor属性指向构造函数。
constructor 属性比较脆弱,当我们修改原型链对象,比如People.prototype.haha=function(){}此时没有任何问题,但是如果用字面量强行更改了这个对象, 此时 xiaoming 的constructor 就丢了。
还有,比如:
此时,newB()实际上实例是A的实例,此时实例的constructor 指向A。
constructor 属性确实在构造函数的 prototype 身上,但是这个属性不可枚举。
也就是说,如果我们遇见
obj . constructor === 构造函数 //true
此时我们可以稍稍认为obj 是这个构造函数的实例,但是也不一定,比如我们上面举的两个例子。
7.3 instanceof 运算符
这个运算符用来检测某一个对象是不是某一个构造函数的实例。
语法:
待检测对象 instanceof 某个函数
此时这个东西不靠谱。
要知道instanceof 的机理,本质上:
对象 instanceof 函数
如果函数的 prototype 在对象的原型链上,此时返回 true ; 反之返回 false 。
换句话说,
如果对象的原型链上,恰好有某一个元素是函数的 prototype ,此时返回 true ; 反之返回 false 。
因为Object . prototype 是所有人的原型链终点,所以任何对象:
任何对象 instanceof Object // true
总结,在JS中,我们没有一种可靠的办法探寻一个元素是不是一个构造函数的实例
鸭式辨型:如果一个动物能够嘎嘎叫,并且走路摇摆,黄色有两只脚,它就是鸭子。
7.4 继承
看看人类和狗类有什么关系,没关系! 计算机领域,关注两个类的关系,就是看属性群之间的关系。
比如,人类和狗类属性群有相交,但是不完全重合,此时可以认为两个类没有任何关系:
人类和小学生类有什么关系,小学生是一类人,小学生肯定是人。人拥有的属性,小学生一定拥有。人拥有的能力,小学生一定也拥有!但是反过来,小学生的属性,人没有,小学生的能力,人也没有。
此时计算机中,小学生继承(extend)了人类
A 继承了 B,此时要意识到:
A 拥有 B 的所有属性和方法,
A 的属性群比 B 大,
A 丰富了 B ,A 把 B 变的更具体,范围更小。
JavaScript 来实现这样的两个类:People类 、Student类,People类拥有的所有属性和方法,Student类的实例都拥有,都能打点调用。Student还能丰富自己的类的属性和方法。
此时很简单, 只需要巧妙设计原型链
jQuery的创始人 john Resig写了一个小包,20多行,解决了JS继承恶心的问题。
https://johnresig.com/about/
7.5 属性归属
看看 a 属性是不是在 obj 对象身上(而不是在原型链上),最好用的方法:
obj.hasOwnProperty("a") ;
不靠谱的:
- in 运算符 ,此时如果 a 属性在原型链身上也会返回true. "a" in obj ; for(var k in obj ) {}此时只会遍历可枚举属性。
- 点语法 / 方括号枚举 obj.a !=undefined //看看是不是 undefined 此时的问题是: 首先如果这个值在原型链上,也能返回值;所以不好判断是不是在自己身上;有 a 属性,并且 a 属性就在自己身上,但是值是undefined,此时大水冲了龙王庙,你误会大了!
- JavaScript 面向对象(七)原型链深入
- 深入javascript面向对象,js的原型链、继承
- Javascript原型,原型链,面向对象
- javascript面向对象(七)原型另外的作用--扩充对象的属性和方法
- Javascript 面向对象原型
- JavaScript面向对象-原型
- [JavaScript面向对象编程指南]-深入理解JavaScript默认的继承方式——原型链
- 前端基础进阶(七):详解面向对象、构造函数、原型与原型链
- javascript面向对象(原型、继承)
- 【深入PHP 面向对象】读书笔记(七)
- javascript面向对象(七)
- JavaScript面向对象技术·原型与原型链
- JavaScript原型面向对象构造
- JavaScript面向对象与原型
- Javascript面向对象与原型
- 【JavaScript】面向对象与原型
- JavaScript:面向对象与原型
- JavaScript面向对象与原型
- Hibernate入门(9):数据过滤
- MFC错误0xc000007b 应用程序无法正常启动 的一种原因
- Js 数组深拷贝方法
- 微信小程序开发(二):获取微信小程序页面带参二维码全流程
- Java之注解
- JavaScript 面向对象(七)原型链深入
- Hibernate入门(10):缓存机制
- 算法竞赛_最长回文子串(含特殊符号输出)_C++
- apidoc生成resuful文档
- python设计模式之模板方法
- JavaWeb(EL表达式学习笔记)
- mysql
- Java开发数据库默认端口及网络常用端口
- 【算法设计作业】Week1