aboutsummaryrefslogtreecommitdiff
path: root/files/zh-cn/web/javascript/guide/working_with_objects/index.html
blob: 28f6dd54d59946be5eb4ba7f0f5c55eb4064c957 (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
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
---
title: 使用对象
slug: Web/JavaScript/Guide/Working_with_Objects
tags:
  - JavaScript
  - 初学者
  - 基本语法
  - 教程
  - 文档
  - 比较对象
translation_of: Web/JavaScript/Guide/Working_with_Objects
---
<div>{{jsSidebar("JavaScript Guide")}} {{PreviousNext("Web/JavaScript/Guide/Text_formatting", "Web/JavaScript/Guide/Details_of_the_Object_Model")}}</div>

<p>JavaScript 的设计是一个简单的基于对象的范式。一个对象就是一系列属性的集合,一个属性包含一个名和一个值。一个属性的值可以是函数,这种情况下属性也被称为<em>方法</em>。除了浏览器里面预定义的那些对象之外,你也可以定义你自己的对象。本章节讲述了怎么使用对象、属性、函数和方法,怎样实现自定义对象。</p>

<h2 id="对象概述">对象概述</h2>

<p>javascript 中的对象(物体),和其它编程语言中的对象一样,可以比照现实生活中的对象(物体)来理解它。 javascript 中对象(物体)的概念可以比照着现实生活中实实在在的物体来理解。</p>

<p>在javascript中,一个对象可以是一个单独的拥有属性和类型的实体。我们拿它和一个杯子做下类比。一个杯子是一个对象(物体),拥有属性。杯子有颜色,图案,重量,由什么材质构成等等。同样,javascript对象也有属性来定义它的特征。</p>

<h2 id="对象和属性">对象和属性</h2>

<p>一个 javascript 对象有很多属性。一个对象的属性可以被解释成一个附加到对象上的变量。对象的属性和普通的 javascript 变量基本没什么区别,仅仅是属性属于某个对象。属性定义了对象的特征(译注:动态语言面向对象的鸭子类型)。你可以通过点符号来访问一个对象的属性。</p>

<div style="margin-right: 270px;">
<pre class="brush: js">objectName.propertyName
</pre>
</div>

<p>和其他 javascript 变量一样,对象的名字(可以是普通的变量)和属性的名字都是大小写敏感的。你可以在定义一个属性的时候就给它赋值。例如,我们创建一个myCar的对象然后给他三个属性,make,model,year。具体如下所示:</p>

<pre class="brush: js">var myCar = new Object();
myCar.make = "Ford";
myCar.model = "Mustang";
myCar.year = 1969; </pre>

<p>对象中未赋值的属性的值为{{jsxref("undefined")}}(而不是{{jsxref("null")}})。</p>

<pre class="brush: js">myCar.noProperty; // undefined
</pre>

<p>JavaScript 对象的属性也可以通过方括号访问或者设置(更多信息查看 <a href="https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/Property_Accessors">property accessors</a>). 对象有时也被叫作关联数组, 因为每个属性都有一个用于访问它的字符串值。例如,你可以按如下方式访问 <code>myCar </code>对象的属性:</p>

<pre class="brush: js">myCar["make"] = "Ford";
myCar["model"] = "Mustang";
myCar["year"] = 1969;
</pre>

<p>一个对象的属性名可以是任何有效的 JavaScript 字符串,或者可以被转换为字符串的任何类型,包括空字符串。然而,一个属性的名称如果不是一个有效的 JavaScript 标识符(例如,一个由空格或连字符,或者以数字开头的属性名),就只能通过方括号标记访问。这个标记法在属性名称是动态判定(属性名只有到运行时才能判定)时非常有用。例如:</p>

<pre><code>// 同时创建四个变量,用逗号分隔
</code>var myObj = new Object(),
    str = "myString",
    rand = Math.random(),
    obj = new Object();

myObj.type              = "Dot syntax";
myObj["date created"]   = "String with space";
myObj[str]              = "String value";
myObj[rand]             = "Random Number";
myObj[obj]              = "Object";
myObj[""]               = "Even an empty string";

console.log(myObj);
</pre>

<p>请注意,方括号中的所有键都将转换为字符串类型,因为JavaScript中的对象只能使用String类型作为键类型。 例如,在上面的代码中,当将键obj添加到myObj时,JavaScript将调用obj.toString()方法,并将此结果字符串用作新键。</p>

<p>你也可以通过存储在变量中的字符串来访问属性:</p>

<div style="width: auto;">
<pre class="brush: js">var propertyName = "make";
myCar[propertyName] = "Ford";

propertyName = "model";
myCar[propertyName] = "Mustang";
</pre>
</div>

<p>你可以在  <a class="internal" href="/zh-CN/docs/JavaScript/Guide/Statements#for...in_Statement" style="line-height: 1.5;" title="zh-CN/docs/JavaScript/Guide/Statements#for...in Statement">for...in</a> 语句中使用方括号标记以枚举一个对象的所有属性。为了展示它如何工作,下面的函数当你将对象及其名称作为参数传入时,显示对象的属性:</p>

<pre class="brush: js">function showProps(obj, objName) {
  var result = "";
  for (var i in obj) {
    if (obj.hasOwnProperty(i)) {
        result += objName + "." + i + " = " + obj[i] + "\n";
    }
  }
  return result;
}
</pre>

<p>因而,对于函数调用 <code>showProps(myCar, "myCar")</code> 将返回以下值:</p>

<pre class="brush: js">myCar.make = Ford
myCar.model = Mustang
myCar.year = 1969
</pre>

<h2 id="枚举一个对象的所有属性">枚举一个对象的所有属性</h2>

<p>从 <a href="/zh-CN/docs/JavaScript/ECMAScript_5_support_in_Mozilla" title="zh-CN/docs/JavaScript/ECMAScript 5 support in Mozilla">ECMAScript 5</a> 开始,有三种原生的方法用于列出或枚举对象的属性:</p>

<ul>
 <li><a href="/zh-CN/docs/JavaScript/Reference/Statements/for...in" title="zh-CN/docs/JavaScript/Reference/Statements/for...in">for...in</a> 循环<br>
  该方法依次访问一个对象及其原型链中所有可枚举的属性。</li>
 <li><a href="/zh-CN/docs/JavaScript/Reference/Global_Objects/Object/keys" title="zh-CN/docs/JavaScript/Reference/Global Objects/Object/keys">Object.keys(o)</a><br>
  该方法返回对象 <code>o</code> 自身包含(不包括原型中)的所有可枚举属性的名称的数组。</li>
 <li><a href="/zh-CN/docs/JavaScript/Reference/Global_Objects/Object/getOwnPropertyNames" title="zh-CN/docs/JavaScript/Reference/Global Objects/Object/getOwnPropertyNames">Object.getOwnPropertyNames(o)</a><br>
  该方法返回对象 <code>o</code> 自身包含(不包括原型中)的所有属性(无论是否可枚举)的名称的数组。</li>
</ul>

<p>在 ECMAScript 5 之前,没有原生的方法枚举一个对象的所有属性。然而,可以通过以下函数完成:</p>

<pre class="brush: js">function listAllProperties(o){
	var objectToInspect;
	var result = [];

	for(objectToInspect = o; objectToInspect !== null; objectToInspect = Object.getPrototypeOf(objectToInspect)){
		result = result.concat(Object.getOwnPropertyNames(objectToInspect));
	}

	return result;
}
</pre>

<p>这在展示 “隐藏”(在原型中的不能通过对象访问的属性,因为另一个同名的属性存在于原型链的早期)的属性时很有用。如果只想列出可访问的属性,那么只需要去除数组中的重复元素即可。</p>

<h2 id="创建新对象">创建新对象</h2>

<p>JavaScript 拥有一系列预定义的对象。另外,你可以创建你自己的对象。从  JavaScript 1.2 之后,你可以通过对象初始化器(Object Initializer)创建对象。或者你可以创建一个构造函数并使用该函数和 <code>new</code> 操作符初始化对象。</p>

<h3 id="使用对象初始化器">使用对象初始化器</h3>

<p>除了通过构造函数创建对象之外,你也可以通过对象初始化器创建对象。使用对象初始化器也被称作通过字面值创建对象。对象初始化器与 C++ 术语相一致。</p>

<p>通过对象初始化器创建对象的语法如下:</p>

<pre class="brush: js">var obj = { property_1:   value_1,   // property_# 可以是一个标识符...
            2:            value_2,   // 或一个数字...
           ["property" +3]: value_3,  //  或一个可计算的key名...
            // ...,
            "property n": value_n }; // 或一个字符串
</pre>



<p>这里 <code>obj</code> 是新对象的名称,每一个 <code>property_<em>i</em></code> 是一个标识符(可以是一个名称、数字或字符串字面量),并且每个 <code>value_<em>i</em></code> 是一个其值将被赋予 property_<em>i </em>的表达式。<code style="font-style: normal; line-height: 1.5;">obj</code> 与赋值是可选的;如果你不需要在其他地方引用对象,你就不需要将它赋给一个变量。(注意在接受一条语句的地方,你可能需要将对象字面量括在括号里,从而避免将字面量与块语句相混淆)</p>

<p>如果一个对象是通过在顶级脚本的对象初始化器创建的,则 JavaScript 在每次遇到包含该对象字面量的表达式时都会创建对象。同样的,在函数中的初始化器在每次函数调用时也会被创建。</p>

<p>下面的语句只有当 <code>cond</code> 表达式的值为 <code>true</code> 时创建对象并将其赋给变量 <code>x</code></p>

<pre class="brush: js">if (cond) var x = {hi: "there"};
</pre>

<p>下例创建了有三个属性的 <code>myHonda</code> 对象。注意它的 <code>engine</code> 属性也是一个拥有自己属性的对象。</p>

<pre class="brush: js">var myHonda = {color: "red", wheels: 4, engine: {cylinders: 4, size: 2.2}};
</pre>

<p>你也可以用对象初始化器来创建数组。参见 {{ web.link("Values%2C_variables%2C_and_literals#Array_literals", "array literals") }}.</p>

<p>在 JavaScript 1.1 及更早版本中,你不能使用对象初始化器。你只能通过使用构造函数或其他对象的函数来创建对象。参见 {{ anch("使用构造函数") }}.</p>

<h3 id="使用构造函数">使用构造函数</h3>

<p>作为另一种方式,你可以通过两步来创建对象:</p>

<ol>
 <li>通过创建一个构造函数来定义对象的类型。首字母大写是非常普遍而且很恰当的惯用法。</li>
 <li>通过 <code>new</code> 创建对象实例。</li>
</ol>

<p>为了定义对象类型,为对象类型创建一个函数以声明类型的名称、属性和方法。例如,你想为汽车创建一个类型,并且将这类对象称为 <code>car</code> ,并且拥有属性 make, model, 和 year,你可以创建如下的函数:</p>

<pre class="brush: js">function Car(make, model, year) {
  this.make = make;
  this.model = model;
  this.year = year;
}
</pre>

<p>注意通过使用 this 将传入函数的值赋给对象的属性。</p>

<p>现在你可以象这样创建一个 <code>mycar</code> 对象:</p>

<pre class="brush: js">var mycar = new Car("Eagle", "Talon TSi", 1993);
</pre>

<p>该创建了 <code>mycar</code> 并且将指定的值赋给它的属性。因而 <code>mycar.make</code> 的值是字符串 "Eagle", <code>mycar.year</code> 的值是整数 1993,依此类推。</p>

<p>你可以通过调用 <code>new</code> 创建任意数量的 <code>car</code> 对象。例如:</p>

<pre class="brush: js">var kenscar = new Car("Nissan", "300ZX", 1992);
var vpgscar = new Car("Mazda", "Miata", 1990);
</pre>

<p>一个对象的属性值可以是另一个对象。例如,假设你按如下方式定义了 <code>person</code> 对象:</p>

<pre class="brush: js">function Person(name, age, sex) {
  this.name = name;
  this.age = age;
  this.sex = sex;
}
</pre>

<p>然后按如下方式创建了两个 <code>person</code> 实例:</p>

<pre class="brush: js">var rand = new Person("Rand McKinnon", 33, "M");
var ken = new Person("Ken Jones", 39, "M");
</pre>

<p>那么,你可以重写 <code>car</code> 的定义以包含一个拥有它的 <code>owner</code> 属性,如:</p>

<pre class="brush: js">function Car(make, model, year, owner) {
  this.make = make;
  this.model = model;
  this.year = year;
  this.owner = owner;
}
</pre>

<p>你可以按如下方式创建新对象:</p>

<pre class="brush: js">var car1 = new Car("Eagle", "Talon TSi", 1993, rand);
var car2 = new Car("Nissan", "300ZX", 1992, ken);
</pre>

<p>注意在创建新对象时,上面的语句将 <code>rand</code><code>ken</code> 作为 <code>owner</code> 的参数值,而不是传入字符串字面量或整数值。接下来你如果想找出 car2 的拥有者的姓名,你可以访问如下属性:</p>

<pre class="brush: js">car2.owner.name
</pre>

<p>注意你总是可以为之前定义的对象增加新的属性。例如,语句</p>

<pre class="brush: js">car1.color = "black";
</pre>

<p><code>car1</code> 增加了 <code>color</code> 属性,并将其值设为 "black." 然而,这并不影响其他的对象。想要为某个类型的所有对象增加新属性,你必须将属性加入到 <code>car </code>对象类型的定义中。</p>

<h3 id="使用_Object.create_方法">使用 Object.create 方法</h3>

<p>对象也可以用 {{jsxref("Object.create()")}} 方法创建。该方法非常有用,因为它允许你为创建的对象选择一个原型对象,而不用定义构造函数。</p>

<pre class="brush: js">// Animal properties and method encapsulation
var Animal = {
  type: "Invertebrates", // 属性默认值
  displayType : function() {  // 用于显示type属性的方法
    console.log(this.type);
  }
}

// 创建一种新的动物——animal1
var animal1 = Object.create(Animal);
animal1.displayType(); // Output:Invertebrates

// 创建一种新的动物——Fishes
var fish = Object.create(Animal);
fish.type = "Fishes";
fish.displayType(); // Output:Fishes
</pre>

<p>该函数更多的信息及详细用法,参见 {{ web.link("/zh-CN/docs/JavaScript/Reference/Global_Objects/Object/create", "Object.create method") }}</p>

<h2 id="继承"><strong>继承</strong></h2>

<p>所有的 JavaScript 对象至少继承于一个对象。被继承的对象被称作原型,并且继承的属性可通过构造函数的 <code>prototype</code> 对象找到。查看更多详细 <a href="https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Inheritance_and_the_prototype_chain">Inheritance and the prototype chain</a></p>

<h2 id="对象属性索引"><strong>对象属性索引</strong></h2>

<p>在 JavaScript 1.0 中,你可以通过名称或序号访问一个属性。但是在 JavaScript 1.1 及之后版本中,如果你最初使用名称定义了一个属性,则你必须通过名称来访问它;而如果你最初使用序号来定义一个属性,则你必须通过索引来访问它。</p>

<p>这个限制发生在你通过构造函数创建一个对象和它的属性(就象我们之前通过 <code>Car</code> 对象类型所做的那样)并且显式地定义了单独的属性(如 <code>m</code>yCar.color = "red")之时。如果你最初使用索引定义了一个对象属性,例如 <code>myCar[5] = "25"</code>,则你只可能通过 <code>myCar[5]</code> 引用它。</p>

<p>这条规则的例外是从与HTML对应的对象,例如 <code>forms</code> 数组。对于这些数组的元素,你总是既可以通过其序号(依据其在文档中出现的顺序),也可以按照其名称(如果有的话)访问它。举例而言,如果文档中的第二个 <code>&lt;form&gt;</code> 标签有一个 <code>NAME</code> 属性且值为<code> "myForm",访问该 form 的方式可以是 document.forms[1],document.forms["myForm"]或 document.myForm。</code></p>

<p>为对象类型定义属性</p>

<p>你可以通过 <code>prototype </code>属性为之前定义的对象类型增加属性。这为该类型的所有对象,而不是仅仅一个对象增加了一个属性。下面的代码为所有类型为 <code>car </code>的对象增加了 <code>color</code> 属性,然后为对象 <code>car1</code><code>color</code> 属性赋值:</p>

<pre class="brush: js">Car.prototype.color = null;
car1.color = "black";
</pre>

<p>参见 <a href="/zh-CN/docs/JavaScript/Reference" style="line-height: 1.5; text-decoration: underline;" title="zh-CN/docs/JavaScript/Reference">JavaScript Reference</a> 中 Function 对象的 <a href="/zh-CN/docs/JavaScript/Reference/Global_Objects/Function/prototype" style="line-height: 1.5;" title="zh-CN/docs/JavaScript/Reference/Global Objects/Function/prototype"><code>prototype</code> 属性</a> 。</p>

<h2 id="定义方法">定义方法</h2>

<p>一个<em>方法</em> 是关联到某个对象的函数,或者简单地说,一个方法是一个值为某个函数的对象属性。定义方法就像定义普通的函数,除了它们必须被赋给对象的某个属性。查看 <a href="https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Functions/Method_definitions">method definitions</a>了解更多详情例如:</p>

<pre class="brush: js">objectName.methodname = function_name;

var myObj = {
  myMethod: function(params) {
    // ...do something
  }

  // 或者 这样写也可以

  myOtherMethod(params) {
    // ...do something else
  }
};
</pre>

<p>这里 <code>objectName</code> 是一个已经存在的对象,<code>methodname</code> 是方法的名称,而 <code style="font-style: normal; line-height: 1.5;">function_name</code> 是函数的名称。</p>

<p>你可以在对象的上下文中象这样调用方法:</p>

<pre class="brush: js">object.methodname(params);
</pre>

<p>你可以在对象的构造函数中包含方法定义来为某个对象类型定义方法。例如,你可以为之前定义的 <code>car</code> 对象定义一个函数格式化并显示其属性:</p>

<pre class="brush: js">function displayCar() {
  var result = `A Beautiful ${this.year} ${this.make} ${this.model}`;
  pretty_print(result);
}
</pre>

<p>这里 <code>pretty_print</code> 是一个显示横线和一个字符串的函数。注意使用 this 指代方法所属的对象。</p>

<p>你可以在对象定义中通过增加下述语句将这个函数变成 <code>Car</code> 的方法:</p>

<pre class="brush: js">this.displayCar = displayCar;
</pre>

<p>因此,<code>Car</code> 的完整定义看上去将是:</p>

<pre class="brush: js">function Car(make, model, year, owner) {
  this.make = make;
  this.model = model;
  this.year = year;
  this.owner = owner;
  this.displayCar = displayCar;
}
</pre>

<p>然后你可以按如下方式为每个对象调用 <code>displayCar</code> 方法:</p>

<pre class="brush: js">car1.displayCar();
car2.displayCar();
</pre>



<h2 id="通过_this_引用对象">通过 <code>this</code> 引用对象</h2>



<p>JavaScript 有一个特殊的关键字 <code>this</code>,它可以在方法中使用以指代当前对象。例如,假设你有一个名为 <code>validate</code> 的函数,它根据给出的最大与最小值检查某个对象的 <code>value</code> 属性:</p>

<pre class="brush: js">function validate(obj, lowval, hival) {
  if ((obj.value &lt; lowval) || (obj.value &gt; hival)) {
    alert("Invalid Value!");
  }
}
</pre>

<p>然后,你可以在每个元素的 <code>onchange</code> 事件处理器中调用 <code>validate</code>,并通过 <code>this</code> 传入相应元素,代码如下:</p>

<pre class="brush: html">&lt;input type="text" name="age" size="3"
  onChange="validate(this, 18, 99)"&gt;
</pre>

<p>总的说来, <code>this</code> 在一个方法中指调用的对象。</p>

<p>当与 <code>form</code> 属性一起使用时,<code>this </code>可以指代当前对象的父窗体。在下面的例子中,窗体 <code>myForm</code> 包含一个 <code>Text </code>对象和一个按钮,当用户点击按键,<code>Text</code> 对象的值被设为窗体的名称。按钮的 <code>onclick</code> 事件处理器使用 <code>this.form</code> 以指代其父窗体,即 <code>myForm</code></p>

<pre class="brush: html">&lt;form name="myForm"&gt;
&lt;p&gt;&lt;label&gt;Form name:&lt;input type="text" name="text1" value="Beluga"&gt;&lt;/label&gt;
&lt;p&gt;&lt;input name="button1" type="button" value="Show Form Name"
     onclick="this.form.text1.value = this.form.name"&gt;
&lt;/p&gt;
&lt;/form&gt;</pre>

<h2 id="定义_getters_与_setters"><strong>定义 getters 与 setters</strong></h2>

<p>一个 <a href="https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Functions/get">getter</a> 是一个获取某个特定属性的值的方法。一个  <a href="https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Functions/set">setter</a> 是一个设定某个属性的值的方法。你可以为预定义的或用户定义的对象定义 getter 和 setter 以支持新增的属性。定义 getter 和 setter 的语法采用对象字面量语法。</p>

<p>下面例子描述了getters 和 setters 是如何为用户定义的对象<code> o</code> 工作的。</p>

<pre class="brush: js">var o = {
  a: 7,
  get b() {
    return this.a + 1;
  },
  set c(x) {
    this.a = x / 2
  }
};

console.log(o.a); // 7
console.log(o.b); // 8
o.c = 50;
console.log(o.a); // 25</pre>

<p><code>o</code> 对象的属性如下:</p>

<ul>
 <li><code>o.a</code> — 数字</li>
 <li><code>o.b</code> — 返回 <code>o.a</code> + 1 的 getter</li>
 <li><code>o.c</code> — 由  <code>o.c 的值所设置 <code>o.a</code> 值的</code> setter</li>
</ul>

<p>请注意在一个对象字面量语法中定义getter和setter使用"[gs]et property()"的方式(相比较于__define[GS]etter__)时,并不是获取和设置某个属性自身,容易让人误以为是"[gs]et propertyName(){ }"这样错误的使用方法。定义一个getter或setter函数使用语法"[gs]et property()",定义一个已经声明的函数作为的getter和setter方法,使用<code><a href="/zh-CN/docs/JavaScript/Reference/Global_Objects/Object/defineProperty" title="zh-CN/docs/Core JavaScript 1.5 Reference/Global
Objects/Object/defineProperty">Object.defineProperty</a></code>(或者 <code><a href="/zh-CN/docs/JavaScript/Reference/Global_Objects/Object/defineGetter" title="zh-CN/docs/Core JavaScript 1.5 Reference/Global
Objects/Object/defineGetter">Object.prototype.__defineGetter__</a></code> 旧语法回退)</p>

<p>下面这个例子展示使用getter和setter方法扩展 {{jsxref("Date")}}原型,为预定义好的Date类添加一个year的属性。定义属性year的getter和setter方法用到了Date类中已存在的getFullYear和setFullYear方法。</p>

<p>定义属性year的getter和setter:</p>

<pre class="brush: js">var d = Date.prototype;
Object.defineProperty(d, "year", {
  get: function() { return this.getFullYear() },
  set: function(y) { this.setFullYear(y) }
});
</pre>

<p>通过一个Date对象使用getter和setter:</p>

<pre class="brush: js">var now = new Date();
console.log(now.year); // 2000
now.year = 2001; // 987617605170
console.log(now);
// Wed Apr 18 11:13:25 GMT-0700 (Pacific Daylight Time) 2001
</pre>

<p>原则上,getter 和 setter 既可以:</p>

<ul>
 <li>使用 <a href="#使用对象初始化器">使用对象初始化器</a> 定义</li>
 <li>也可以之后随时使用 getter 和 setter 添加方法添加到任何对象</li>
</ul>

<p>当使用 <a href="#使用对象初始化器">使用对象初始化器</a> 的方式定义getter和setter时,只需要在getter方法前加get,在setter方法前加set,当然,getter方法必须是无参数的,setter方法只接受一个参数(设置为新值),例如:</p>

<pre class="brush: js">var o = {
  a: 7,
  <strong>get</strong> b() { return this.a + 1; },
  <strong>set</strong> c(x) { this.a = x / 2; }
};
</pre>

<p>使用Object.defineProperties的方法,同样也可以对一个已创建的对象在任何时候为其添加getter或setter方法。这个方法的第一个参数是你想定义getter或setter方法的对象,第二个参数是一个对象,这个对象的属性名用作getter或setter的名字,属性名对应的属性值用作定义getter或setter方法的函数,下面是一个例子定义了和前面例子一样的getter和setter方法:</p>

<pre class="brush: js">var o = { a:0 }

Object.defineProperties(o, {
    "b": { get: function () { return this.a + 1; } },
    "c": { set: function (x) { this.a = x / 2; } }
});

o.c = 10 // Runs the setter, which assigns 10 / 2 (5) to the 'a' property
console.log(o.b) // Runs the getter, which yields a + 1 or 6
</pre>

<p>这两种定义方式的选择取决于你的编程风格和手头的工作量。当你定义一个原型准备进行初始化时,可以选择第一种方式,这种方式更简洁和自然。但是,当你需要添加getter和setter方法 —— 因为并没有编写原型或者特定的对象 ——使用第二种方式更好。第二种方式可能更能表现JavaScript语法的动态特性——但也会使代码变得难以阅读和理解。</p>

<h2 id="删除属性">删除属性</h2>

<p>你可以用 <a href="https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/delete">delete</a> 操作符删除一个<strong style="color: red;">不是继承而来</strong>的属性。下面的例子说明如何删除一个属性:</p>

<pre class="brush: js">//Creates a new object, myobj, with two properties, a and b.
var myobj = new Object;
myobj.a = 5;
myobj.b = 12;

//Removes the a property, leaving myobj with only the b property.
delete myobj.a;
</pre>

<p>如果一个全局变量不是用 <code>var</code> 关键字声明的话,你也可以用 <code>delete</code> 删除它:</p>

<pre class="brush: js">g = 17;
delete g;
</pre>

<p>参见<code>{{ web.link("Expressions_and_operators#delete", "delete") }}</code> 以获取更多信息。</p>

<h2 id="比较对象">比较对象</h2>

<p>在 JavaScript 中 objects 是一种引用类型。两个独立声明的对象永远也不会相等,即使他们有相同的属性,只有在比较一个对象和这个对象的引用时,才会返回true.</p>

<pre class="brush: js">// 两个变量, 两个具有同样的属性、但不相同的对象
var fruit = {name: "apple"};
var fruitbear = {name: "apple"};

fruit == fruitbear // return false
fruit === fruitbear // return false
</pre>

<div class="note">
<p><strong>注意:</strong> "===" 运算符用来检查数值是否相等: 1 === "1"返回false,而1 == "1" 返回true</p>
</div>

<pre class="brush: js">// 两个变量, 同一个对象
var fruit = {name: "apple"};
var fruitbear = fruit;  // 将fruit的对象<strong>引用</strong>(reference)赋值给 fruitbear
                        // 也称为将fruitbear“<em><strong>指向</strong></em>”fruit对象
// fruit与fruitbear都指向同样的对象
fruit == fruitbear // return true
fruit === fruitbear // return true</pre>

<p>了解更多关于比较操作符的用法,查看 <a href="https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/Comparison_Operators">Comparison operators</a>.</p>

<h2 id="附加参考">附加参考</h2>

<ul>
 <li>想要深入了解,请阅读<a href="https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Guide/Details_of_the_Object_Model">details of javaScript's objects model</a></li>
 <li>想要学习 ECMAScript 2015中类(一种创建对象的新方式),请阅读 <a href="https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Classes">JavaScript classes</a> 章节。</li>
</ul>



<p>{{PreviousNext("Web/JavaScript/Guide/Regular_Expressions", "Web/JavaScript/Guide/Details_of_the_Object_Model")}}</p>

<div></div>