Object.create()

╰+哭是因爲堅強的太久メ 2023-06-13 06:05 55阅读 0赞
  1. Object.create(proto, [propertiesObject])
  2. //方法创建一个新对象,使用现有的对象来提供新创建的对象的proto。

参数:

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

返回值:
在指定原型对象上添加新属性后的对象。

Object.create()与new Object()
在js中,创建对象有三种方式

  • {} // 对象字面量
  • new Object()
  • Object.create()

1和2的区别很小,1不能传参,2可以传参。
new Object() 和Object.create() 区别就比较大了

new关键字
new 关键字做了几件事
(1)创建一个新对象
(2)将新对象的原型指向构造函数的原型
(3)执行构造函数,绑定this
(4)返回这个对象

比如创建一个Car对象,伪代码

  1. // new Car()
  2. var obj = new Object()
  3. obj._proto_ = Car.prototype
  4. // 执行构造函数, 绑定this
  5. Car.call(obj)

我们注意到比较关键的地方是,它调用了Car对象的构造函数,并通过call将obj的this绑定到了Car对象上,这一步操作将Car对象上的属性,继承到了obj上。

Object.create()
它同样是创建一个新对象,将新对象的原型关联到构造函数上

  1. var f = function() {
  2. }
  3. f.prototype = Car
  4. return new f()

比较鲜明的地方是在继承的时候
子类去继承父类的原型方法的时候,很多人会这样写

  1. // 父类是People,子类是Male
  2. Male.prototype = new People()

new确实能够继承,但是调用了父类的构造函数,把父类的属性也给继承到了原型上,但是我们仅仅只是想要父类的原型方法,所以这样写是存在副作用的
正确的写法应该是

  1. Male.prototype = Object.create(People.prototype)

这种方式,不会调用父类的构造函数,而是生成新对象,将新对象与父类原型关联,然后new这个新对象返回,将 new 构造函数的方式转变了成 new 新对象的方式,这样就更加纯净,干脆。

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

  1. // new Object() 方式创建
  2. var a = {
  3. rep : 'apple' }
  4. var b = new Object(a)
  5. console.log(b) // {rep: "apple"}
  6. console.log(b.__proto__) // {}
  7. console.log(b.rep) // {rep: "apple"}
  8. // Object.create() 方式创建
  9. var a = {
  10. rep: 'apple' }
  11. var b = Object.create(a)
  12. console.log(b) // {}
  13. console.log(b.__proto__) // {rep: "apple"}
  14. console.log(b.rep) // {rep: "apple"}

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

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

  1. // 创建一个以另一个空对象为原型,且拥有一个属性p的对象
  2. o = Object.create({
  3. }, {
  4. p: {
  5. value: 42 } })
  6. // 省略了的属性特性默认为false,所以属性p是不可写,不可枚举,不可配置的:
  7. o.p = 24
  8. o.p
  9. //42
  10. o.q = 12
  11. for (var prop in o) {
  12. console.log(prop)
  13. }
  14. //"q"
  15. delete o.p
  16. //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__ 实现的

  1. var proto = {
  2. y: 20,
  3. z: 40,
  4. showNum(){
  5. }
  6. };
  7. var o = Object.create(proto);

在这里插入图片描述
如果是不用Object,create()方法,我们是如何给对象原型添加属性和方法的?
-——- 通过构造函数或者类,例如:

  1. //创建一个构造函数或者类
  2. var People = function(){
  3. }
  4. People.prototype.y = 20
  5. People.prototype.showNum = function() {
  6. }
  7. //通过构造函数创建实例
  8. var p = new People();
  9. console.log(p.__proto__ === People.prototype) // true

在这里插入图片描述
Object.setPrototypeOf
描述:该方法的作用与 proto 相同,用来设置一个对象的 prototype 对象,返回参数对象本身。它是 ES6 正式推荐的设置原型对象的方法。
格式:Object.setPrototypeOf(object, prototype)
用法:

  1. var proto = {
  2. y: 20,
  3. z: 40
  4. };
  5. var o = {
  6. x: 10 };
  7. Object.setPrototypeOf(o, proto);

在这里插入图片描述
输出结果中看出,添加的方法是在原型上的。就类似于

  1. obj.__proto__ = proto;

Object.getPrototypeOf()
描述:用于读取一个对象的原型对象;
格式:Object.getPrototypeOf(obj);
用法:

  1. Object.getPrototypeOf('foo') === String.prototype // true
  2. Object.getPrototypeOf(true) === Boolean.prototype // true

Object.create实现类式继承
下面的例子演示了如何使用Object.create()来实现类式继承。这是一个所有版本JavaScript都支持的单继承。

  1. // Shape - 父类(superclass)
  2. function Shape() {
  3. this.x = 0;
  4. this.y = 0;
  5. }
  6. // 父类的方法
  7. Shape.prototype.move = function(x, y) {
  8. this.x += x;
  9. this.y += y;
  10. console.info('Shape moved.');
  11. };
  12. // Rectangle - 子类(subclass)
  13. function Rectangle() {
  14. Shape.call(this); // call super constructor.
  15. }
  16. // 子类续承父类
  17. Rectangle.prototype = Object.create(Shape.prototype);
  18. Rectangle.prototype.constructor = Rectangle;
  19. var rect = new Rectangle();
  20. console.log('Is rect an instance of Rectangle?',
  21. rect instanceof Rectangle); // true
  22. console.log('Is rect an instance of Shape?',
  23. rect instanceof Shape); // true
  24. rect.move(1, 1); // Outputs, 'Shape moved.'

如果你希望能继承到多个对象,则可以使用混入的方式。

  1. function MyClass() {
  2. SuperClass.call(this);
  3. OtherSuperClass.call(this);
  4. }
  5. // 继承一个类
  6. MyClass.prototype = Object.create(SuperClass.prototype);
  7. // 混合其它
  8. Object.assign(MyClass.prototype, OtherSuperClass.prototype);
  9. // 重新指定constructor
  10. MyClass.prototype.constructor = MyClass;
  11. MyClass.prototype.myMethod = function() {
  12. // do a thing
  13. };

使用 Object.create 的 propertyObject参数

  1. var o;
  2. // 创建一个原型为null的空对象
  3. o = Object.create(null);
  4. o = {
  5. };
  6. // 以字面量方式创建的空对象就相当于:
  7. o = Object.create(Object.prototype);
  8. o = Object.create(Object.prototype, {
  9. // foo会成为所创建对象的数据属性
  10. foo: {
  11. writable:true,
  12. configurable:true,
  13. value: "hello"
  14. },
  15. // bar会成为所创建对象的访问器属性
  16. bar: {
  17. configurable: false,
  18. get: function() {
  19. return 10 },
  20. set: function(value) {
  21. console.log("Setting `o.bar` to", value);
  22. }
  23. }
  24. });
  25. function Constructor(){
  26. }
  27. o = new Constructor();
  28. // 上面的一句就相当于:
  29. o = Object.create(Constructor.prototype);
  30. // 当然,如果在Constructor函数中有一些初始化代码,Object.create不能执行那些代码
  31. // 创建一个以另一个空对象为原型,且拥有一个属性p的对象
  32. o = Object.create({
  33. }, {
  34. p: {
  35. value: 42 } })
  36. // 省略了的属性特性默认为false,所以属性p是不可写,不可枚举,不可配置的:
  37. o.p = 24
  38. o.p
  39. //42
  40. o.q = 12
  41. for (var prop in o) {
  42. console.log(prop)
  43. }
  44. //"q"
  45. delete o.p
  46. //false
  47. //创建一个可写的,可枚举的,可配置的属性p
  48. o2 = Object.create({
  49. }, {
  50. p: {
  51. value: 42,
  52. writable: true,
  53. enumerable: true,
  54. configurable: true
  55. }
  56. });

参考:Object.create()
Object.create()方法
js 中 new 与 Object.create()的区别

发表评论

表情:
评论列表 (有 0 条评论,55人围观)

还没有评论,来说两句吧...

相关阅读