aboutsummaryrefslogtreecommitdiff
path: root/files/zh-cn/web/javascript/reference/global_objects/object/create/index.html
blob: 255cd9ec0cdca769393c5c9ddaea937f9d21fc2c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
---
title: Object.create()
slug: Web/JavaScript/Reference/Global_Objects/Object/create
tags:
  - ECMAScript5
  - JavaScript
  - Method
  - Object
  - Reference
  - polyfill
translation_of: Web/JavaScript/Reference/Global_Objects/Object/create
---
<div>{{JSRef}}</div>

<p><strong><code>Object.create()</code></strong>方法创建一个新对象,使用现有的对象来提供新创建的对象的__proto__。 (请打开浏览器控制台以查看运行结果。)</p>

<div>{{EmbedInteractiveExample("pages/js/object-create.html", "taller")}}</div>

<h2 id="Syntax" name="Syntax">语法</h2>

<pre>Object.create(<var>proto,[</var><var>propertiesObject</var>])</pre>

<h3 id="Parameters" name="Parameters">参数</h3>

<dl>
 <dt><code>proto</code></dt>
 <dd>新创建对象的原型对象。</dd>
 <dt><code>propertiesObject</code></dt>
 <dd>可选。需要传入一个对象,该对象的属性类型参照{{jsxref("Object.defineProperties()")}}的第二个参数。如果该参数被指定且不为 {{jsxref("undefined")}},该传入对象的自有可枚举属性(即其自身定义的属性,而不是其原型链上的枚举属性)将为新创建的对象添加指定的属性值和对应的属性描述符。</dd>
</dl>

<h3 id="Parameters" name="Parameters">返回值</h3>

<p>一个新对象,带着指定的原型对象和属性。</p>

<h3 id="Description" name="Description">例外</h3>

<p>如果<code>proto</code>参数不是 {{jsxref("null")}} 或非原始包装对象,则抛出一个 {{jsxref("TypeError")}} 异常。</p>

<h2 id="Examples" name="Examples">例子</h2>

<h3 id="用_Object.create实现类式继承">用 <code>Object.create</code>实现类式继承</h3>

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

<pre class="brush: js">// Shape - 父类(superclass)
function Shape() {
  this.x = 0;
  this.y = 0;
}

// 父类的方法
Shape.prototype.move = function(x, y) {
  this.x += x;
  this.y += y;
  console.info('Shape moved.');
};

// Rectangle - 子类(subclass)
function Rectangle() {
  Shape.call(this); // call super constructor.
}

// 子类续承父类
Rectangle.prototype = Object.create(Shape.prototype);
Rectangle.prototype.constructor = Rectangle;

var rect = new Rectangle();

console.log('Is rect an instance of Rectangle?',
  rect instanceof Rectangle); // true
console.log('Is rect an instance of Shape?',
  rect instanceof Shape); // true
rect.move(1, 1); // Outputs, 'Shape moved.'</pre>

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

<pre class="brush: js">function MyClass() {
     SuperClass.call(this);
     OtherSuperClass.call(this);
}

// 继承一个类
MyClass.prototype = Object.create(SuperClass.prototype);
// 混合其它
Object.assign(MyClass.prototype, OtherSuperClass.prototype);
// 重新指定constructor
MyClass.prototype.constructor = MyClass;

MyClass.prototype.myMethod = function() {
     // do a thing
};
</pre>

<p><a href="https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/assign">Object.assign</a> 会把  <code>OtherSuperClass</code>原型上的函数拷贝到 <code>MyClass</code>原型上,使 MyClass 的所有实例都可用 OtherSuperClass 的方法。Object.assign 是在 ES2015 引入的,且可用<a href="/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/assign#Polyfill"> polyfilled</a>。要支持旧浏览器的话,可用使用 <a href="https://api.jquery.com/jQuery.extend/">jQuery.extend()</a> 或者 <a href="https://lodash.com/docs/#assign">_.assign()</a></p>

<h3 id="使用_Object.create_的_propertyObject参数">使用 <code>Object.create</code><code>propertyObject</code>参数</h3>

<pre class="brush: js">var o;

// 创建一个原型为null的空对象
o = Object.create(null);


o = {};
// 以字面量方式创建的空对象就相当于:
o = Object.create(Object.prototype);


o = Object.create(Object.prototype, {
  // foo会成为所创建对象的数据属性
  foo: {
    writable:true,
    configurable:true,
    value: "hello"
  },
  // bar会成为所创建对象的访问器属性
  bar: {
    configurable: false,
    get: function() { return 10 },
    set: function(value) {
      console.log("Setting `o.bar` to", value);
    }
  }
});


function Constructor(){}
o = new Constructor();
// 上面的一句就相当于:
o = Object.create(Constructor.prototype);
// 当然,如果在Constructor函数中有一些初始化代码,Object.create不能执行那些代码


// 创建一个以另一个空对象为原型,且拥有一个属性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

//创建一个可写的,可枚举的,可配置的属性p
o2 = Object.create({}, {
  p: {
    value: 42,
    writable: true,
    enumerable: true,
    configurable: true
  }
});</pre>

<h2 id="Polyfill" style="line-height: 24px;">Polyfill</h2>

<p>这个 polyfill 涵盖了主要的应用场景,它创建一个已经选择了原型的新对象,但没有把第二个参数考虑在内。</p>

<p>请注意,尽管在 ES5 中 <code>Object.create</code>支持设置为<code>[[Prototype]]</code><code>null</code>,但因为那些ECMAScript5以前版本限制,此 polyfill 无法支持该特性。</p>

<pre class="brush: js">if (typeof Object.create !== "function") {
    Object.create = function (proto, propertiesObject) {
        if (typeof proto !== 'object' &amp;&amp; typeof proto !== 'function') {
            throw new TypeError('Object prototype may only be an Object: ' + proto);
        } else if (proto === null) {
            throw new Error("This browser's implementation of Object.create is a shim and doesn't support 'null' as the first argument.");
        }

        if (typeof propertiesObject !== 'undefined') throw new Error("This browser's implementation of Object.create is a shim and doesn't support a second argument.");

        function F() {}
        F.prototype = proto;

        return new F();
    };
}</pre>

<h2 id="规范" style="margin-bottom: 20px; line-height: 30px;">规范</h2>

<table class="standard-table">
 <tbody>
  <tr>
   <th scope="col">Specification</th>
   <th scope="col">Status</th>
   <th scope="col">Comment</th>
  </tr>
  <tr>
   <td>{{SpecName('ES5.1', '#sec-15.2.3.5', 'Object.create')}}</td>
   <td>{{Spec2('ES5.1')}}</td>
   <td>Initial definition. Implemented in JavaScript 1.8.5.</td>
  </tr>
  <tr>
   <td>{{SpecName('ES2015', '#sec-object.create', 'Object.create')}}</td>
   <td>{{Spec2('ES2015')}}</td>
   <td></td>
  </tr>
  <tr>
   <td>{{SpecName('ESDraft', '#sec-object.create', 'Object.create')}}</td>
   <td>{{Spec2('ESDraft')}}</td>
   <td></td>
  </tr>
 </tbody>
</table>

<h2 id="浏览器兼容">浏览器兼容</h2>

<p>{{Compat("javascript.builtins.Object.create")}}</p>

<h2 id="See_also" name="See_also" style="margin-bottom: 20px; line-height: 30px;">相关链接</h2>

<ul>
 <li>{{jsxref("Object.defineProperty")}}</li>
 <li>{{jsxref("Object.defineProperties")}}</li>
 <li>{{jsxref("Object.prototype.isPrototypeOf")}}</li>
 <li>John Resig's post on <a class="external external-icon" href="http://ejohn.org/blog/objectgetprototypeof/" style="white-space: pre-line;" title="http://ejohn.org/blog/objectgetprototypeof/">getPrototypeOf</a></li>
</ul>