深入理解JavaScript-Object.create

简介: 深入理解JavaScript-Object.create

2006年,Douglas Grockford 写了一篇文章:《JavaScript 中的原型式继承》(”Prototypal Inheritance in JavaScript“)。这篇文章介绍了一种不涉及严格意义上构造函数的继承方法。他的出发点是即使不自定义类型也可以通过原型继承对象之间的信息共享。文章最终给出了一个函数:


function object(o) {
  function F(){}
  F.prototype = o
  return new F()
}


于是乎,《JavaScript 高级程序设计》中的 JavaScript 就多了一种——原型式继承

于是乎,ECMAScript 5 新增了 Object.create() 方法将原型式继承的概念规范化


用法



var obj = Object.create({name: 'johan', age: 23}) // obj 继承了属性name 和 age
var obj2 = Object.create(null) // obj2 不继承任何属性和方法
var obj3 = Object.create(Object.prototype) // 与 {} 和 new Object() 一个意思
var obj4 = Object.create({}, {
    property1: {
        value: true,
        writable: true
    }
}) // 第二个参数与 Object.defineProperties() 一致


图解 Object.create 实现



function create(proto) {
    function F(){}
    F.prototype = proto
    return new F()
}


第一步: function F(){}

即创建一个函数,因为约定首字母大写,视为构造函数,创建函数 F 时,F 构造函数与和它的原型对象就有了这一层的关系:


F.prototype === F.prototype; // 假设你把F.prototype当作一个值
F.prototype.constructor === F;

image.png


第二步:F.prototype = proto

即将 F.prototype 赋值为传入的 proto,如此就打破了F.prototype = F.prototype 以及 F.prototype.constructor = F ,它们的关系为

image.png


第三步:return new F()

第三步的解读有点费解,因为这里涉及到 new 的操作,在 new 改变了对象 中我们说过,new 会创建一个对象,并将这个对象的隐式原型(__proto__) 指向构造函数的原型对象,并初始化构造函数,如果值则返回值。我们也会在后续的原型(后续文章会对其介绍) 中介绍,new 是隐式原型继承,Object.create 是显式原型继承


在这里,我们按实现 new 的方式来解读 return new F()new F 后的实例的 __proto__ 指向的是 F.prototype,而这个值已经在第二步时指给了传来的 proto,所以就有了new F().__proto__ = proto

image.png


或许你还是不太清楚第三步,我们结合例子,就一目了然了

var obj = Object.create({name: 'johan'})


第三步的图解就成了这样:

image.png


这样就成了, obj 继承自{name: johan} 这个对象,至于F.prototype = {name: 'johan'},在调用完 Object.create 之后,也因为没人使用 F 函数而被引擎当作垃圾回收了,遂成了obj.__proto__ = {name: 'johan'}

如此「原型式继承」就被传承下来了


其原理就是如此,简单来说,就是创建空(构造)函数,关联它的原型(实现继承)


Object.create(null)


在阅读源码时,常会看到 Object.create(null) ,用此初始化一个新对象,至于为什么用这个方法而不用 new Object 或者 {},是因为无论 new 还是字面量,都是继承自 Object 构造函数,而使用Object.create(null) ,能得到一个没有任何继承痕迹的对象


var obj = Object.create(null)


不信,你可以打印 obj 试试

讲完了 new 和 Object.create ,我们来看看原型(后续文章会介绍)

相关文章
|
JavaScript 前端开发 小程序
js 实现浏览器下载视频2种方法
js 实现浏览器下载视频2种方法
1875 0
|
8月前
|
SQL 数据可视化 BI
挖掘QuickBI产品的独特价值——模板市场一键应用篇
模板市场一键应用的独特价值在于: - 所见即所得、丰富的数据看板模板参考,提效业务人员工作方式及时间,对于数据人来说,日常大量的数据需要分析,追求更快地赋能业务决策,同时可以有效降低设计数据看板的时长耗用,是BI产品很重要的一项落地企业业务的能力; - 一键应用按钮减少了业务人员对产品的学习成本、操作成本; - 拖拉拽字段的操作本身是敏捷BI工具相较于其它数据处理方式(如SQL、Python、Excel)的一大超越,但替换数据集的支持直接节省了用户进行拖拉拽,可谓又是一增效点。同时也可以帮助日常业务人员(非专业数据处理人员)快速理解他需要提供的分析数据的数据类型。
190 1
Redisson 分布式锁的正确使用
你会正确使用分布式锁吗?
2545 0
Redisson 分布式锁的正确使用
|
C++ 开发者
C++课程设计:图书管理系统【附源码】
图书管理系统,C++ 实现,附全套源码
5664 2
C++课程设计:图书管理系统【附源码】
|
存储 分布式计算 NoSQL
大数据-136 - ClickHouse 集群 表引擎详解1 - 日志、Log、Memory、Merge
大数据-136 - ClickHouse 集群 表引擎详解1 - 日志、Log、Memory、Merge
342 0
|
搜索推荐 数据挖掘 API
淘宝商品API接口的对接及收益
淘宝商品API接口是淘宝开放平台提供的数据服务,支持商品搜索、详情、评价等功能,帮助开发者快速获取商品数据,提升用户体验,降低运营成本,增强市场竞争力,并支持数据分析和业务决策。对接流程包括注册账号、获取API密钥、阅读文档、编写请求代码、发送请求、解析数据、错误处理和日志记录等步骤。通过实际案例,如价格比较网站、库存管理工具、个性化推荐系统等,展示了API接口的应用价值。
420 5
|
缓存 数据库 开发者
后端开发中的性能优化策略
在后端开发领域,性能优化是提升用户体验和系统稳定性的关键。本文将探讨几种有效的后端性能优化技术,包括数据库查询优化、缓存机制的应用、代码层面的优化以及系统架构的调整。通过这些策略,开发者可以显著提高应用程序的响应速度和处理能力,从而满足现代Web应用对高性能的需求。
|
机器学习/深度学习 设计模式 自然语言处理
【算法分析与设计】算法概述
【算法分析与设计】算法概述
|
程序员 开发者
IDEA插件-Rainbow Brackets彩虹括号
DEA插件-Rainbow Brackets是一款用于增强IDEA开发环境的工具,它可以帮助开发者更好地管理和展示代码中的括号。
3987 0
IDEA插件-Rainbow Brackets彩虹括号
|
前端开发
css动画(仿微信聊天页面)
css动画(仿微信聊天页面)