浅谈JS的原型和继承


Posted in Javascript onMay 08, 2019

参考文献

JavaScript原型与继承的秘密

__proto__

除null和undefined,JS中的所有数据类型都有这个属性; 它表示当我们访问一个对象的某个属性时,如果该对象自身不存在该属性, 就从它的__proto__属性上继续查找,以此类推,直到找到,若找到最后还是没有找到,则结果为undefined

我们把一个对象的__proto__属性所指向的对象叫该对象的原型;我们可以修改一个对象的原型来让这个对象拥有某种属性或某个方法

// 修改一个Number类型的值的原型
const num = 1;
num.__proto__.name = "My name is 1";
console.log(num.name); // My name is 1
 
// 修改一个对象的原型
const obj = {};
obj.__proto__.name = "dreamapple";
console.log(obj.name); // dreamapple

需注意的是,__proto__属性虽多数浏览器支持,但其实它仅在ECMAScript 2015规范中才被准确定义, 目的是为了给这个传统的功能定制一个标准,以确保浏览器间的兼容性。通过使用__proto__属性来修改一个对象的原型非常慢且影响性能。 所以,若想获取一个对象的原型,推荐用Object.getPrototypeOf 或Reflect.getPrototypeOf,设置一个对象的原型推荐用Object.setPrototypeOf或Reflect.setPrototypeOf

prototype

首先要记住的是,该属性一般只存在于函数对象上; 只要是能作为构造器的函数,都包含这个属性。即只要这个函数能通过new生成一个新对象, 那么这个函数肯定具有prototype属性。因为我们自定义的函数都可通过new生成一个对象,所以我们自定义的函数都有prototype 这个属性

// 函数字面量
console.log((function(){}).prototype); // {constructor: ƒ}
 
// Date构造器
console.log(Date.prototype); // {constructor: ƒ, toString: ƒ, toDateString: ƒ, toTimeString: ƒ, toISOString: ƒ, …}
 
// Math.abs 不是构造器,不能通过new操作符生成一个新的对象,所以不含有prototype属性
console.log(Math.abs.prototype); // undefined

prototype属性有什么作用呢?作用就是:函数通过new生成的一个对象, 这个对象的原型(__proto__)指向该函数的prototype属性:

// 其中F表示一个自定义的函数或者是含有prototype属性的内置函数
new F().__proto__ === F.prototype // true
 
// 通过函数字面量定义的函数的__proto__属性都指向Function.prototype
(function(){}).__proto__ === Function.prototype // true
 
// 通过对象字面量定义的对象的__proto__属性都是指向Object.prototype
({}).__proto__ === Object.prototype // true
 
// Object函数的原型的__proto__属性指向null
Object.prototype.__proto__ === null // true
 
// 因为Function本身也是一个函数,所以Function函数的__proto__属性指向它自身的prototype
Function.__proto__ === Function.prototype // true
 
// 因为Function的prototype是一个对象,所以Function.prototype的__proto__属性指向Object.prototype
Function.prototype.__proto__ === Object.prototype // true

constructor

constructor表示一个对象的构造函数,除null和undefined,JS中的所有数据类型都有这个属性; 我们可通过下面的代码来验证一下:

null.constructor // Uncaught TypeError: Cannot read property 'constructor' of null ...
undefined.constructor // Uncaught TypeError: Cannot read property 'constructor' of undefined ...
 
(true).constructor // ƒ Boolean() { [native code] }
(1).constructor // ƒ Number() { [native code] }
"hello".constructor // ƒ String() { [native code] }

一个对象的constructor属性确切地说并不是存在这个对象上面的; 而是存在这个对象的原型上(如果是多级继承需手动修改原型的constructor属性),我们可用下面的代码来解释一下:

const F = function() {};
// 当我们定义一个函数的时候,这个函数的prototype属性上面的constructor属性指向自己本身
F.prototype.constructor === F; // true

对JS的原始类型(string, number, boolean, null, undefined, symbol (new in ECMAScript 2015)),它们的constructor属性是只读的,不可修改:

(1).constructor = "something";
console.log((1).constructor); // 输出 ƒ Number() { [native code] }

如果真想改这些原始类型的constructor属性,也不是不可以:

Number.prototype.constructor = "number constructor";
(1).constructor = 1;
console.log((1).constructor); // 输出 number constructor

当然上面的方式不推荐

以上所述是小编给大家介绍的JS原型和继承详解整合,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!

Javascript 相关文章推荐
js脚本学习 比较实用的基础
Sep 07 Javascript
js创建一个input数组并绑定click事件的方法
Jun 12 Javascript
修复jQuery tablesorter无法正确排序的bug(加千分位数字后)
Mar 30 Javascript
Vue.js动态组件解析
Sep 09 Javascript
js的OOP继承实现(必看篇)
Feb 18 Javascript
Bootstrap Table从零开始
Jun 30 Javascript
JavaScript数组push方法使用注意事项
Oct 30 Javascript
vue仿淘宝订单状态的tab切换效果
Jun 23 Javascript
Vue组件和Route的生命周期实例详解
Feb 10 Javascript
微信小程序使用map组件实现获取定位城市天气或者指定城市天气数据功能
Jan 22 Javascript
JavaScript 禁止用户保存图片的实现代码
Apr 28 Javascript
antd-DatePicker组件获取时间值,及相关设置方式
Oct 27 Javascript
vue使用vuex实现首页导航切换不同路由的方法
May 08 #Javascript
微信小程序封装自定义弹窗的实现代码
May 08 #Javascript
Vue.js轮播图走马灯代码实例(全)
May 08 #Javascript
深入浅析vue-cli@3.0 使用及配置说明
May 08 #Javascript
js实现继承的方法及优缺点总结
May 08 #Javascript
微信小程序人脸识别功能代码实例
May 07 #Javascript
iphone刘海屏页面适配方法
May 07 #Javascript
You might like
基于php伪静态的实现详细介绍
2013/04/28 PHP
创建无限极分类树型结构的简单方法
2017/06/20 PHP
PHP实现上传图片到数据库并显示输出的方法
2018/05/31 PHP
总结PHP代码规范、流程规范、git规范
2018/06/18 PHP
PHP封装的数据库模型Model类完整示例【基于PDO】
2019/03/14 PHP
jQuery+PHP实现图片上传并提交功能
2020/07/27 PHP
告诉大家什么是JSON
2008/06/10 Javascript
jQuery 对象中的类数组操作
2009/04/27 Javascript
jquery1.4后 jqDrag 拖动 不可用
2010/02/06 Javascript
JavaScript 嵌套函数指向this对象错误的解决方法
2010/03/15 Javascript
jQuery中Ajax的get、post等方法详解
2015/01/20 Javascript
JQuery基础语法小结
2015/02/27 Javascript
js和jQuery设置Opacity半透明 兼容IE6
2016/05/24 Javascript
js实现登录与注册界面
2017/11/01 Javascript
JavaScript 数组去重并统计重复元素出现的次数实例
2017/12/14 Javascript
安装Node.js并启动本地服务的操作教程
2018/05/12 Javascript
详解node.js的http模块实例演示
2018/07/12 Javascript
vue 权限认证token的实现方法
2018/07/17 Javascript
vue项目引入Iconfont图标库的教程图解
2018/10/24 Javascript
解决vue-pdf查看pdf文件及打印乱码的问题
2020/11/04 Javascript
Python解析网页源代码中的115网盘链接实例
2014/09/30 Python
python使用fork实现守护进程的方法
2017/11/16 Python
Python子类继承父类构造函数详解
2019/02/19 Python
浅谈Python基础—判断和循环
2019/03/22 Python
详解利用Python scipy.signal.filtfilt() 实现信号滤波
2019/06/05 Python
python热力图实现简单方法
2021/01/29 Python
彪马荷兰官网:PUMA荷兰
2019/05/08 全球购物
如何判断一段程序是由C 编译程序还是由C++编译程序编译的
2013/08/04 面试题
项目资料员岗位职责
2013/12/10 职场文书
影视动画专业个人的自我评价
2013/12/31 职场文书
消防标语大全
2014/06/07 职场文书
工作证明书
2015/06/15 职场文书
大卫科波菲尔读书笔记
2015/06/30 职场文书
漫画「请问您今天要来点兔子吗?」最新杂志彩页公开
2022/03/24 日漫
在NumPy中深拷贝和浅拷贝相关操作的定义和背后的原理
2022/04/14 Python
小程序实现侧滑删除功能
2022/06/25 Javascript