Object.create(..)和new(..)的内部实现
Object.create()
经常会有这样的疑问?Object.create()到底做了什么工作? 像这样两行代码有什么不同?
var obj ={a: 1}
var b = obj
var c = Object.create(obj)
复制代码
我们来做一点事情,
var obj ={a: 1}
var b = obj
console.log(obj.a) // 1
console.log(b.a) // 1
b.a = 2
console.log(obj.a) //2
复制代码
var obj ={a: 1}
var b = Object.create(obj)
console.log(obj.a) // 1
console.log(b.a) // 1
b.a = 2
console.log(obj.a) //1
复制代码
所以我们立马可以想到Object.create貌似创建了一个新的对象,这个对象继承(关联)了obj的属性,改变新对象的同名属性并不会影响原对象。
如果直接用“=”来赋值,只是一个对象的引用。
那么,为什么会这样呢?是因为Object.create()复制了一个新对象么?实际上并不是,只是Object.create()返回了一个新的空对象,并且这个空对象的构造函数的原型(prototype)是指向obj的。所以当我们访问新对象b.a的时候实际上是通过原型链访问的obj中的a。
当我们试图修改b.a的时候,这里有一个知识点(对象的遮蔽效应,如果修改对象的一个与原型链同名属性,那么会在当前对象中新建一个改属性,这个属性拥有更高级的访问优先级,所以就会遮蔽原型链中的同名属性)
所以Object.create的具体内部实现模拟
_create = function (o) {let F = function () {}F.prototype = oreturn new F()
}
复制代码
再来看这个例子
var person = {friends : ["Van","Louis","Nick"]
};
var anotherPerson = _create(person);
anotherPerson.friends.push("Rob");
var yetAnotherPerson = _create(person);
yetAnotherPerson.friends.push("Style");
alert(person.friends);//"Van,Louis,Nick,Rob,Style"复制代码
相当于做了一次浅复制,新创建的各个对象实际上是会共享原始对象中的引用类型的值,这意味着person.friends不仅属于person所有,而且也会被anotherPerson以及yetAnotherPerson共享
实际上真正的Object.create()还可以传入第二个参数,这个参数与Object.defineProperties方法的第二个参数格式相同, 通过第二个参数是会在新对象中重新创建一个属性的,然后通过属性遮蔽原理避免修改原对象。
var person = {name : "Van"
};
var anotherPerson = Object.create(person, {name : {value : "Louis"}
});
alert(anotherPerson.name);//"Louis"
复制代码
Object.create(null) 会创建一个真正的空对象,并没有继承Object原型链上的方法
var a = {} 这并不是一个纯粹的空对象,它会继承原型链上的很多方法
new()
关于new的内部实现模拟
function _new () {// arguments实际上是一个类数组对象,需要转成数组let args = [].slice.call(arguments)// 第一个参数是构造函数,把它拿出来let constructor = args.shift()// Object.create()返回一个新对象,这个对象的构造函数的原型指向Foolet context = Object.create(constructor.prototype)// 在返回的context对象环境中执行构造函数,为新的context添加属性let result = constructor.apply(context, args)// 如果Foo显示的返回了一个对象,那么应该直接返回这个对象,而不用理会以上所有的操作,一般不会发生这种情况,但是new的实现的确是这样的逻辑// 这里之所以判断类型是否为object还要添加 != null 的判断,是因为null的typeof结果也是‘object’// 不同的对象在底层都表示为二进制,在Javascript中二进制前三位都为0的话会被判断为Object类型,null的二进制表示全为0,自然前三位也是0,所以执行typeof时会返回"object"return (typeof result === 'object' && result != null) ? result : context
}function Foo (name) {this.name = name
}Foo.prototype.getName = function() {console.log(this.name)
}var a = _new(Foo, 'tom')
a.getName()复制代码
实际上new操作符, 就是通过Object.ctreate()创建一个新的对象,这个对象的原型指向构造函数,并且在新建对象的上下文环境中执行构造函数,初始化新建对象的属性。
总结
当然这里的实现只是一个模拟实现,至于就是内部真正的实现方式必然是复杂得多。比如说这里的new方法和Object.create()必然不会相互引用,这样会产生一个无限循环的函数,所以说这里只是一个大概思路上的引导,对于理解js的对象继承,原型链的概念会有帮助。
转载于:https://juejin.im/post/5bf37a5ee51d4552da47dae9
Object.create(..)和new(..)的内部实现相关推荐
- 关于Object.create()与原型链的面试题?
原文地址 https://segmentfault.com/q/1010000004670616?utm_source=weekly&utm_medium=email&utm_camp ...
- js学习日记-new Object和Object.create到底干了啥
function Car () {this.color = "red"; } Car.prototype.sayHi=function(){console.log('你好') }v ...
- firefox-Developer开发者站点——关于Object.create()新方法的介绍
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/create Objec ...
- object.create()
语法: Object.create(proto, [propertiesObject]) //方法创建一个新对象,使用现有的对象来提供新创建的对象的proto. 参数: proto : 必须.表示新建 ...
- js-new、object.create、bind的模拟实现【转载备忘】
//创建Person构造函数,参数为name,age function Person(name,age){this.name = name;this.age = age; }function _new ...
- 原生js实现Object.assign和Object.create
Object.assign(target,-sources) Object.assign(target,-source)方法用于将所有可枚举的属性的值从一个或多个源对象复制到目标对象.它将返回目标对象 ...
- Object.create()和Object.assign()
一.Object.create() 该方法用于创建一个新对象,并为其指定原型对象和属性. 语法:Object.create(prototype,description); proto:(必须),表示新 ...
- Object.create()和new Object()
Object.create(null) 创建的对象是一个空对象,在该对象上没有继承 Object.prototype 原型链上的属性或者方法,例如:toString(), hasOwnProperty ...
- Object.create()方法
Object.create()方法创建一个新对象,使用现有的对象来提供新创建的对象的proto. 语法:Object.create(proto, [propertiesObject]) - proto ...
最新文章
- 使用pytest对django项目单元测试
- Svchost.exe病毒
- python课程与c+课程有什么不同-南通渡课少儿编程:python和C的区别是什么?
- 使用Spring-data-jpa(1)(三十)
- nginx+keepalived高可用及双主模式
- 【开卷故意】记录一次高并发下的死锁解决思考过程
- linux 脚本 java_Linux 通过脚本执行Java程序
- Ngrok tunnel本地映射公网使用方案
- 用python如何制作表格步骤_Python中用xlwt制作表格实例讲解
- Flutter BuildOwner之inactive Elements浅析
- 整理Java基础知识--数组2
- 【SegMap: 3D Segment Mapping using Data-Driven Descriptors】
- UnixVi命令详解
- 零基础学SQL(三、MYSQL环境变量配置及启动)
- zktime 协议_ZKtime5.0考勤软件说明书
- android studio keymap eclipse,android studio eclipse keymap theme 快捷键 主题风格设置
- 数学中的两个重要极限公式
- 电脑上怎样下载喜马拉雅里的 Mp3
- java.lang.IllegalStateException: 由于没有提供multi-part配置,无法处理parts
- 解决数据迁移过程中主键冲突的问题