当前位置: 首页 > 编程日记 > 正文

object.create()

  1. 语法:

    Object.create(proto, [propertiesObject])

    //方法创建一个新对象,使用现有的对象来提供新创建的对象的proto

  2. 参数:
proto : 必须。表示新建对象的原型对象,即该参数会被赋值到目标对象(即新对象,或说是最后返回的对象)的原型上。该参数可以是null对象, 函数的prototype属性 (创建空的对象时需传null , 否则会抛出TypeError异常)。propertiesObject : 可选。 添加到新创建对象的可枚举属性(即其自身的属性,而不是原型链上的枚举属性)对象的属性描述符以及相应的属性名称。这些属性对应Object.defineProperties()的第二个参数。 3 返回值:
在指定原型对象上添加新属性后的对象。

  1. 案例说明:

1)创建对象的方式不同

new Object() 通过构造函数来创建对象, 添加的属性是在自身实例下。
Object.create() es6创建对象的另一种方式,可以理解为继承一个对象, 添加的属性是在原型下。

// new Object() 方式创建
var a = {  rep : 'apple' } var b = new Object(a) console.log(b) // {rep: "apple"} console.log(b.__proto__) // {} console.log(b.rep) // {rep: "apple"} // Object.create() 方式创建 var a = { rep: 'apple' } var b = Object.create(a) console.log(b) // {} console.log(b.__proto__) // {rep: "apple"} console.log(b.rep) // {rep: "apple"} 

Object.create()方法创建的对象时,属性是在原型下面的,也可以直接访问 b.rep // {rep: "apple"} ,
此时这个值不是吧b自身的,是它通过原型链proto来访问到b的值。



2)创建对象属性的性质不同

// 创建一个以另一个空对象为原型,且拥有一个属性p的对象
o = Object.create({}, { p: { value: 42 } }) // 省略了的属性特性默认为false,所以属性p是不可写,不可枚举,不可配置的: o.p = 24 o.p //42 o.q = 12 for (var prop in o) { console.log(prop) } //"q" delete o.p //false 

Object.create() 用第二个参数来创建非空对象的属性描述符默认是为false的,而构造函数或字面量方法创建的对象属性的描述符默认为true。看下图解析:




3)创建空对象时不同


当用构造函数或对象字面量方法创建空对象时,对象时有原型属性的,即有_proto_;
当用Object.create()方法创建空对象时,对象是没有原型属性的。



4)__proto__ 属性
JavaScript 的对象继承是通过原型链实现的。ES6 提供了更多原型对象的操作方法。
__proto__属性(前后各两个下划线),用来读取或设置当前对象的prototype对象。目前只有浏览器环境必须部署有这个属性,其他运行环境不一定要部署,因此不建议使用这个属性,而是使用下面这些来 Object.setPrototypeOf()(写操作)、Object.getPrototypeOf()(读操作)、Object.create()(生成操作)代替。

  • Object.create()
    描述:该方法创建一个新对象,使用现有的对象来提供新创建的对象的__proto__
    格式:Object.create(proto[, propertiesObject])
    用法:如果用传统的方法要给一个对象的原型上添加属性和方法,是通过 __propt__ 实现的
var o = {}
o.prototype.y = 20
o.__proto__.showNum = function(){ } 

现在有 Object.create() 就简单的多了。

var proto = {y: 20,z: 40, showNum(){} }; var o = Object.create(proto); 

  • Object.setPrototypeOf
    描述:该方法的作用与 __proto__ 相同,用来设置一个对象的 prototype 对象,返回参数对象本身。它是 ES6 正式推荐的设置原型对象的方法。
    格式:Object.setPrototypeOf(object, prototype)
    用法:
var proto = {y: 20,z: 40 }; var o = { x: 10 }; Object.setPrototypeOf(o, proto); 

输出结果中看出,添加的方法是在原型上的。就类似于

obj.__proto__ = proto;

  • Object.getPrototypeOf()
    描述:用于读取一个对象的原型对象;
    格式:Object.getPrototypeOf(obj);
    用法:
Object.getPrototypeOf('foo') === String.prototype // true Object.getPrototypeOf(true) === Boolean.prototype // true 



4.1)原型属性的继承
这里结合一个例子来说说这几个方法的使用:
场景:拷贝一个构造函数的实例。

var triangle = {a: 1, b: 2, c: 3}; function ColoredTriangle() { this.color = 'red'; } //ColoredTriangle.prototype = triangle; //ColoredTriangle.prototype.constructor === ColoredTriangle// false Object.assign(ColoredTriangle.prototype, triangle) //ColoredTriangle.prototype.constructor === ColoredTriangle// true var c = new ColoredTriangle(); 

打印出 实例c 看看结构是怎样的



其中 color 属性在实例上,而其他的原型上。
现在来拷贝一个 实例 c2

var c2 = Object.assign({},c)
console.log(c2.color); //red console.log(c2.a); //undefined 

因为 Object.assign是不能拷贝到继承或原型上的方法的。所以 实例c2 没有 a 这个属性。那要怎么要才能拷贝到原型上的方法呢?

4.1.1)第一种方法

var originProto = Object.getPrototypeOf(c);
var originProto2 = Object.create(originProto); var c2 = Object.assign(originProto2, c); //var c2 = Object.assign(Object.create(Object.getPrototypeOf(c)), c) console.log(c2.color); // red console.log(c2.a); // 1 

这样就实现了原型属性的拷贝。
Object.getPrototypeOf(c) 既 originProto 得到的是原型上的 //{a: 1, b: 2, c: 3};
Object.create(originProto) 既 originProto2 既是创建了一个 {a: 1, b: 2, c: 3} 在原型上的新对象;
Object.assign(originProto2, c) 在源对象originProto2 上合并对象 c;

4.1.2)第二种方法 (推荐)

var c = new ColoredTriangle();
var c2 = Object.create(Object.getPrototypeOf(c), Object.getOwnPropertyDescriptors(c)); console.log(c2.color); // red console.log(c2.a); // 1 

可以把Object.create()的参数理解为:第一个参数是放在新对象的原型上的,第二个参数是放在新对象的实例上的。
所以上面例子
Object.getPrototypeOf() 得到的是 c 对象的原型,然后作为第一个参数,所以会在新对象c2 的原型上。
Object.getOwnPropertyDescriptors() 得到是 c 对象自身的可枚举属性,作为第二个参数,放在 c2 的实例上。

为什么说推荐这个方法呢?因为Object.assign() 方法不能正确拷贝 get ,set 属性。

例如,我们给 c 实例添加一个 "colorGet" 属性,并设置该属性的get 描述符:

var c = new ColoredTriangle();
Object.defineProperty(c,'colorGet', { enumerable: true, // 设为可枚举,不然 Object.assign 方法会过滤该属性 get(){ return "Could it return " + this.color } }); var c3 = Object.assign(Object.create(Object.getPrototypeOf(c)), c) 

结果如下:



这里没有拷贝到 "colorGet" 的 get 描述符,而是直接把获取到的值赋值给 "colorGet" 。

那对于 get 描述符要怎么获取呢? Object.getOwnPropertyDescriptors就专为解决这问题而生。
而又因为要拷贝原型上的属性,所以结合Object.create、Object.getPrototypeOf 方法一起使用。即上面的第二种实现方法,如下:

var c = new ColoredTriangle();
Object.defineProperty(c,'colorGet', { enumerable: true, // 设为可枚举,不然 Object.assign 方法会过滤该属性 get(){ return "Could it return " + this.color } }); var c3 = Object.create(Object.getPrototypeOf(c), Object.getOwnPropertyDescriptors(c)); 

结果如下:


此时已经成功的拷贝到了get描述符啦。
虽然说实际开发上很少会要去修改 get 描述符,但是知道多一种方法,遇到这种情况时就知道该怎么去解决了。

注意:这些都只是一个层级的深拷贝。




上面实现 原型属性拷贝 中的两种方法中用到了 Object.getOwnPropertyDescriptorsObject.assing()Object.createObject.getPrototypeOf()方法,通常这几种方法都有一起结合使用。
如果上面的例子还不理解,这里把他简单的拿到 对象的继承 来讲解。理解的话就可以忽略啦。



4.2)原型属性的继承
以前,继承另一个对象,常常写成下面这样。

const obj = {__proto__: prot,foo: 123,
};

ES6 规定__proto__只有浏览器要部署,其他环境不用部署。如果去除__proto__,可以用 Object.create() 和 Object.assign() 来实现。

//现在可以这样写 方法1
const obj = Object.create(prot);
obj.foo = 123; // 或者 方法2 const obj = Object.assign( Object.create(prot), { foo: 123, } ); // 或者 方法3 const obj = Object.create(prot,Object.getOwnPropertyDescriptors({ foo: 123 })); 

但是 Object.assign() 无法正确拷贝get属性和set属性的问题。例如:

var prot = {x: 1, y: 2} var obj = { __proto__: prot, foo: 100, bar(){ return this.foo}, get baz() {return this.foo} }; var obj2 = Object.assign(Object.create(prot), obj) 

上图中,obj 对象的 foo 属性是一个取值函数,Object.assign不会复制这个取值函数,只会拿到值以后,将这个值赋上去。

而 Object.getOwnPropertyDescriptors() 可以解决这个问题 实现get 、set 属性的正确拷贝,即方法3 ,如下:

var prot = {x: 1, y: 2} var obj = { __proto__: prot, foo: 100, bar(){ return this.foo}, get baz() {return this.foo} }; var obj2 = Object.create(prot, Object.getOwnPropertyDescriptors(obj)) 



说了那么多种拷贝方法,怎么去选择呢,还是要看实际应用中的情况:

如果只是拷贝 自身可枚举属性,就可以只用 Object.assign 方法;
如果是要拷贝原型上的属性,就需要 Object.assign , Object.create, Object.getPrototypeOf 方法结合使用
如果是拷贝get /set 属性,就需要 结合 Ojbect.getOwnPropertyDescriptors 方法

转载于:https://www.cnblogs.com/QianDingwei/p/10888472.html

相关文章:

codecheck_use_record

文章目录Step 1: Integrate CodeChecker into your build systemStep 2: Analyze your codeStep 3: Run the analysisStep 4: View the analysis results in the command lineStep 5: Hint: You can do the 1st and the 2nd step in one round by executing checkstep 6: Expor…

centos6.5 rsync+inotify同步配置笔记

以两台服务器为例: 主服务器: 192.168.1.100 从服务器: 192.168.1.101 1.安装rsync (主服务器与从服务器同时安装) 使用xinetd管理rsync yum install rsync xinetd 设置开机启动 vi /etc/xinetd.d/rsync ... 修改为 disable no ... 启动xin…

HOG 特征计算实现

// 获取HOG直方图 cv::Mat getHog(Point pt,std::vector<Mat> &integrals) {// 判断当前点的位置是否符合条件 if( pt.x - R < 0 ||pt.y - R < 0 ||pt.x R > integrals[0].cols ||pt.y R > integrals[0].rows ){return Mat();}// 直方图Mat hist(Size(…

Spring+SpringMVC+Mybatis整合

一、简单测试工程搭建1、Mybatis所需要的的jar包&#xff08;包含数据库驱动包和相关的日志包&#xff09;、SpringMVC和Spring的jar包2、然后构建一个基本的工程&#xff0c;这里我们使用mapper代理的方式进行Mybatis的编写&#xff0c;关于mapper代理请参考Mybatis简单入门中…

【Tools】Markdown数学符号公式(史上最全公式表)

Markdown数学符号&公式 文章目录Markdown数学符号&公式1. 希腊字母表2. 希腊字母3. 数学符号表4. 数学符号5. 数学符号补充表6. 数学符号补充1. 希腊字母表 符号代码符号代码α\alphaα\alphaA\AlphaA\Alphaβ\betaβ\betaB\BetaB\Betaγ\gammaγ\gammaΓ\GammaΓ\gam…

Editplus下载、安装并最佳配色方案(强烈推荐)

不多说&#xff0c;直接上干货&#xff01; Editplus下载 第一步&#xff1a;进入官网 https://www.editplus.com/ 第二步&#xff1a;下载 https://www.editplus.com/download.html Editplus安装 我这里&#xff0c;直接以一个压缩包来安装&#xff0c;需要的&#xff0c;请…

MySQL数据库开发规范-EC

最近一段时间一边在线上抓取SQL来优化&#xff0c;一边在整理这个开发规范&#xff0c;尽量减少新的问题SQL进入生产库。今天也是对公司的开发做了一次培训&#xff0c;PPT就不放上来了&#xff0c;里面有十来个生产SQL的案例。因为规范大部分还是具有通用性&#xff0c;所以也…

操作系统与内存管理

操作系统内存管理 文章目录操作系统内存管理1. 虚拟地址空间2. 内存地址空间含义及分配3. 虚拟内存诞生的前世与今生&#xff1f;3.1 内存管理的好处3.2 **内存管理实现总体策略**4. 不同进程如何划分内存地址空间&#xff1f;5 内存分配与回收5.1 buffer和cache5.2 malloc背后…

圆形 LBP 特征

template <typename _Tp> staticinline void elbp_(InputArray _src, OutputArray _dst,int radius, int neighbors) {// 得到数据矩阵Mat src _src.getMat();// 输出矩阵_dst.create(src.rows-2*radius, src.cols-2*radius, CV_32SC1);Mat dst _dst.getMat();// 初始化…

40个Java多线程问题总结

&#xff08;转&#xff09; 这篇文章作者写的真是不错 40个问题汇总 1、多线程有什么用&#xff1f; 一个可能在很多人看来很扯淡的一个问题&#xff1a;我会用多线程就好了&#xff0c;还管它有什么用&#xff1f;在我看来&#xff0c;这个回答更扯淡。所谓"知其然知其所…

SLAM十四讲笔记1

文章目录ch02 初识SLAMch02-01 经典视觉SLAM框架ch02-02 SLAM问题的数学表述ch03 三维空间刚体运动ch03.01 旋转矩阵&#xff1a;点和向量,坐标系01 向量a在线性空间的基[e1,e2,e3][e_1,e_2,e_3][e1​,e2​,e3​]下的坐标为[a1,a2,a3]T[a_1,a_2,a_3]^T[a1​,a2​,a3​]T.02 向量…

12、OpenCV实现图像的空间滤波——图像平滑

1、空间滤波基础概念 1、空间滤波基础 空间滤波一词中滤波取自数字信号处理&#xff0c;指接受或拒绝一定的频率成分&#xff0c;但是空间滤波学习内容实际上和通过傅里叶变换实现的频域的滤波是等效的&#xff0c;故而也称为滤波。空间滤波主要直接基于领域&#xff08;空间域…

计算 LBP 特征

#include <opencv2/opencv.hpp> #include <opencv2/highgui/highgui.hpp> #include <opencv2/features2d/features2d.hpp> #include <opencv2/features2d/features2d.hpp> // 计算原始LBP特征 cv::Mat OLBP(cv::Mat& srcImage) {const int nRows …

三维重建【四】-------------------结构光 三维重建----论文调研

1. 动态目标实时三维重建-结构光方案 动态目标 三维重建 Stripe boundary codes for real-time structured-light range scanning of moving objects 我们提出了一种新的实时结构光扫描方法。在分析现有结构光技术的基本假设之后&#xff0c;我们基于编码投影条纹之间的边界&…

APP开发定制

app是什么意思? APP&#xff0c;application的简称&#xff0c;是智能手机的第三方应用程序&#xff0c;常见的有微信、手机qq、今日头条、手机支付宝、腾讯视频、微店等&#xff0c;随着智能手机和ipad等移动终端设备的普及&#xff0c;人们逐渐习惯了使用APP客户端上网的方式…

Haar 特征提取

double HaarExtract(double const ** image ,int type_, cv::Rect roi) {double value;double wh1, wh2;double bk1, bk2;int x roi.x;int y roi.y;int width roi.width;int height roi.height;switch (type_){// Haar水平边缘case 0: // HaarHEdgewh1 calcIntegral(image…

awk的基本⽤法

awk的基本⽤法 awk是报告⽣成器&#xff0c;格式化⽂本输出&#xff0c;有多种版本。centos中的是gawk即GNU awk版本。 awk⼯作原理&#xff1a;第⼀步&#xff1a;执⾏BEGIN{action;...}语句块中的语句。第⼆步&#xff1a;从⽂件或标准输⼊&#xff08;stdin&#xff09;读取…

视音频数据处理入门:RGB、YUV像素数据处理【转】

转自&#xff1a;http://blog.csdn.net/leixiaohua1020/article/details/50534150 视音频数据处理入门系列文章&#xff1a; 视音频数据处理入门&#xff1a;RGB、YUV像素数据处理 视音频数据处理入门&#xff1a;PCM音频采样数据处理 视音频数据处理入门&#xff1a;H.264视频…

SVO(SVO: fast semi-direct monocular visual odometry)

SVO&#xff08;SVO: fast semi-direct monocular visual odometry&#xff09;翻译 文章目录SVO&#xff08;SVO: fast semi-direct monocular visual odometry&#xff09;翻译1、介绍2、系统概述3、符号4、运动估计4.1、 基于稀疏模型的图像对齐4.2、 通过特征对齐松弛4.3、…

MSER 候选车牌区域检测

#include "opencv2/highgui/highgui.hpp" #include "opencv2/features2d/features2d.hpp" #include "opencv2/imgproc/imgproc.hpp" #include <iostream> // Mser车牌目标检测 std::vector<cv::Rect> mserGetPlate(cv::Mat srcImage…

从HelloWorld看Knative Serving代码实现

为什么80%的码农都做不了架构师&#xff1f;>>> 摘要&#xff1a; Knative Serving以Kubernetes和Istio为基础&#xff0c;支持无服务器应用程序和函数的部署并提供服务。我们从部署一个HelloWorld示例入手来分析Knative Serving的代码细节。 概念先知 官方给出的这…

svo_note

SVO论文笔记1.frame overviews2. Motion Estimate Thread2.1 Sparse Model-based Image Alignment 基于稀疏点亮度的位姿预估2.2 Relaxation Through Feature Alignment 基于图块的特征点匹配2.3 Pose and Structure Refinement3 Mapping Thread3.1 depth-filter3.2 初始化参考…

Druid 配置 wallfilter

这个文档提供基于Spring的各种配置方式 使用缺省配置的WallFilter <bean id"dataSource" class"com.alibaba.druid.pool.DruidDataSource" init-method"init" destroy-method"close">...<property name"filters" v…

vue下的bootstrap table + jquery treegrid, treegrid无法渲染的问题

在mian.js导入的包如下&#xff1a;该bootstrap-table-treegrid.js需要去下载&#xff0c;在复制到jquery-treegrid/js/ 1 import $ from jquery 2 import bootstrap/dist/css/bootstrap.min.css 3 import bootstrap/dist/js/bootstrap.min 4 import bootstrap-table/dist/boot…

内存和缓存的区别

今天看书的时候又看到了内存和缓存&#xff0c;之所以说又&#xff0c;是因为之前遇到过查过资料&#xff0c;但是现在又忘了(图侵删)。 所以又复习一遍&#xff0c;记录一下&#xff0c;有所纰漏的地方&#xff0c;欢迎指正。 同志们&#xff0c;上图并不是内存和缓存中的任何…

【Boost】noncopyable:不可拷贝

【CSDN】&#xff1a;boost::noncopyable解析 【Effective C】&#xff1a;条款06_若不想使用编译器自动生成地函数&#xff0c;就该明确拒绝 1.example boost::noncopyable 为什么要boost::noncopyable 在c中定义一个类的时候&#xff0c;如果不明确定义拷贝构造函数和拷贝赋…

BigData NoSQL —— ApsaraDB HBase数据存储与分析平台概览

一、引言时间到了2019年&#xff0c;数据库也发展到了一个新的拐点&#xff0c;有三个明显的趋势&#xff1a; 越来越多的数据库会做云原生(CloudNative)&#xff0c;会不断利用新的硬件及云本身的优势打造CloudNative数据库&#xff0c;国内以阿里云的Cloud HBase、POLARDB为代…

ubuntu clion 创建桌面快捷方式

ubuntu clion 创建桌面快捷方式 首先在终端下输入 cd /usr/share/applications/进入applications目录下&#xff0c;建立一个clion.desktop文件 sudo touch clion.desktop然后在vim命令下编辑该文件 sudo vim clion.desktop进入vim后&#xff0c;按i插入开始编辑该文件&…

Flex 布局:语法篇

2019独角兽企业重金招聘Python工程师标准>>> 布局的传统解决方案&#xff0c;基于盒状模型&#xff0c;依赖 display 属性 position 属性 float 属性。它对于那些特殊布局非常不方便&#xff0c;比如&#xff0c;垂直居中就不容易实现。 2009年&#xff0c;W3C 提…

特征运动点估计

cv::Mat getRansacMat(const std::vector<cv::DMatch>& matches, const std::vector<cv::KeyPoint>& keypoints1, const std::vector<cv::KeyPoint>& keypoints2, std::vector<cv::DMatch>& outMatches) {// 转换特征点格式std::vecto…