创建新对象的方法
一、创建新对象:字面量、构造器、Object.create()、class关键字
对象初始化器 / 字面值 / 字面量 / 语法结构
一、语法:通过使用带有可选属性列表的花括号{…}来创建对象
var obj = {
property_1: value_1, // property_# 可以是一个标识符
2: value_2, // 数字
['property' + 3]: value_3, // 可计算的Key名
// ...
'property n': value_n, // 字符串
}
1、obj 是新对象的名称,每一个 property_i 是一个标识符(可以是一个名称、数字或字符串字面量),并且每个 value_i 是一个其值将被赋予 property_i 的表达式。
2、obj 与赋值是可选的;
3、如果你不需要在其他地方引用对象,你就不需要将它赋给一个变量。(注意在接受一条语句的地方,你可能需要将对象字面量括在括号里,从而避免将字面量与块语句相混淆)
| 【示例】只有当cond表达式的值为true时创建对象并将其赋值给变量x```javascript if (cond) var x = { hi: ‘there’ }
|
| --- |
4、尾随(trailing)或悬挂(hanging)逗号:列表中的最后一个属性应以逗号结尾(不强制要求有逗号)
| 【示例】```javascript
let user = {
name: "John",
age: 30, // 尾随逗号 / 悬挂逗号。这样便于我们添加、删除和移动属性,因为所有的行都是相似的。
}
| | —- |
二、如果一个对象是通过在顶级脚本的对象初始化器创建的,则JavaScript在每次遇到包含该对象字面量的表达式时都会创建对象。在函数中的初始化器在每次函数调用时也会被创建。
三、使用语法结构创建的对象、生成原型链
| 【示例】```javascript var o = {a: 1};
// o 这个对象继承了 Object.prototype 上面的所有属性 // o 自身没有名为 hasOwnProperty 的属性 // hasOwnProperty 是 Object.prototype 的属性 // 因此 o 继承了 Object.prototype 的 hasOwnProperty // Object.prototype 的原型为 null // 原型链如下: // o —-> Object.prototype —-> null
var a = [“yo”, “whadup”, “?”];
// 数组都继承于 Array.prototype // (Array.prototype 中包含 indexOf, forEach 等方法) // 原型链如下: // a —-> Array.prototype —-> Object.prototype —-> null
function f(){ return 2; }
// 函数都继承于 Function.prototype // (Function.prototype 中包含 call, bind等方法) // 原型链如下: // f —-> Function.prototype —-> Object.prototype —-> null
|
| --- |
四、使用 const 声明的对象是可以被修改的
| 【示例】```javascript
const user = {
name: "John"
};
user.name = "Pete"; // 似乎会触发一个错误,但实际并没有
// const声明仅固定了user的值,而不是值(该对象)里面的内容
alert(user.name); // Pete
1、仅当我们尝试将user=…作为一个整体进行赋值时,const会抛出错误。
2、有另一种将对象属性变为常量的方式,见属性标志和属性描述符:https://www.yuque.com/tqpuuk/yrrefz/xg43a2 |
| —- |
【示例】以下哪一条Javascript代码会产生运行错误? A. var obj=( ); B. var obj=[ ]; C. var obj={ }; D. var obj=/ /; 答案:A 解析:考察点:创建新对象的方法-字面量 A. 语法错误 B,声明obj为数组对象 C,声明obj为对象 D,声明obj为正则对象。若为var obj = //;即赋值被注释掉,及运行被结束 |
---|
计算属性
一、当创建一个对象时,我们可以在对象字面量中使用方括号。这叫做计算属性。
| 【示例】```javascript let fruit = prompt(“Which fruit to buy?”, “apple”);
let bag = { [fruit]: 5, // 属性名是从 fruit 变量中得到的 };
alert( bag.apple ); // 5 如果 fruit=”apple”
1、计算属性的含义很简单:[fruit]含义是属性名应该从fruit变量中获取。<br />2、所以,如果一个用户输入"apple",bag将变为{apple: 5}。<br />3、本质上,这跟下面的语法效果相同:```javascript
let fruit = prompt("Which fruit to buy?", "apple");
let bag = {};
// 从 fruit 变量中获取值
bag[fruit] = 5;
| | —- |
| 【示例】可以在方括号中使用更复杂的表达式:```javascript let fruit = ‘apple’; let bag = { [fruit + ‘Computers’]: 5 // bag.appleComputers = 5 };
|
| --- |
<a name="0ff9e1962cd266d295481c760c7e7ac6"></a>
## 使用构造器 / 构造函数
一、在JavaScript中,构造器其实就是一个普通的函数。当使用new操作符来作用这个函数时,就可以被称为构造方法(构造函数)<br />二、构造函数在技术上是常规函数。不过有两个约定:<br />1、它们的命名以大写字母开头。<br />2、它们只能由"new"操作符来执行。<br />三、可以通过两步来创建对象<br />1、通过创建一个构造函数来定义对象的类型。首字母大写是非常普遍而且很恰当的惯用法。<br />2、通过new创建对象实例。<br />四、当一个函数被使用new操作符执行时,它按照以下步骤:<br />1、一个新的空对象被创建
- 将这个空对象的原型,指向构造函数的prototype属性
- 将这个空对象分配给this:将空对象赋值给函数内部的this关键字
2、函数体执行。通常它会修改this,为其添加新的属性。<br />3、返回this的值。
| 【示例】换句话说,new User(name)做的就是类似的事情```javascript
function User(name) {
// this = {};(隐式创建)
// 添加属性到 this
this.name = name;
this.isAdmin = false;
// return this;(隐式返回)
}
1、所以new User(‘Jack’)的结果是相同的对象```javascript let user = { name: “Jack”, isAdmin: false };
2、如果我们想创建其他用户,我们可以调用new User("Ann"),new User("Alice")等。比每次都使用字面量创建要短得多,而且更易于阅读。 |
| --- |
五、如果没有参数,我们可以省略new后的括号:
| 【示例】这里省略括号不被认为是一种“好风格”,但是规范允许使用该语法。```javascript
let user = new User; // <-- 没有参数
// 等同于
let user = new User();
| | —- |
六、为了定义对象类型,为对象类型创建一个函数以声明类型的名称、属性和方法。
| 【示例】想为汽车创建一个类型,并且将这类对象称为car,并且拥有属性 make, model 和 year,可以创建如下函数```javascript function Car(make, model, year) { this.make = make // 通过this将传入函数的值赋给对象的属性 this.model = model this.year = year }
// 创建一个mycar对象,将指定的值赋给它的属性 var mycar = new Car(‘Eagle’, ‘Talon TSi’, 1993)
|
| --- |
<a name="P909G"></a>
### 使用构造函数构建对象的方式
一、使用构造函数构建对象的方式:用function来模拟无参的构造函数、用function来模拟有参构造函数来实现、工厂方式、原型方式、混合方式<br />二、构造器的主要目的:实现可重用的对象创建代码。
<a name="hMUJX"></a>
#### function(函数)来模拟class
<a name="hXY8g"></a>
##### 用function来模拟无参的构造函数
| 【示例】```javascript
function Person(){}
var person=new Person();//定义一个function,如果使用new"实例化",该function可以看作是一个Class
person.name="Mark";
person.age="25";
person.work=function(){
alert(person.name+" hello...");
}
person.work();
| | —- |
用function来模拟有参构造函数来实现(用this关键字定义构造的上下文属性)
| 【示例】```javascript function User(name) { this.name = name; this.isAdmin = false; }
let user = new User(“Jack”);
alert(user.name); // Jack alert(user.isAdmin); // false
|
| --- |
| 【示例】```javascript
// 定义了person对象
function Person(name, age, sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
// 创建了两个person实例
var rand = new Person("Rand McKinnon", 33, "M");
var ken = new Person("Ken Jones", 39, "M");
function Car(make, model, year, owner) {
this.make = make;
this.model = model;
this.year = year;
this.owner = owner;
}
var car1 = new Car("Eagle", "Talon TSi", 1993, rand); // 将rand作为owner的参数值,而不是传入字符串字面量或整数值
var car2 = new Car("Nissan", "300ZX", 1992, ken);
console.log(car2.owner.name) // car2的拥有者的姓名
car1.color = 'black' // 可以为之前定义的对象增加新的属性,这并不影响其他的对象
// 想要为某个类型的所有对象添加属性,必须将属性加入到car对象类型的定义中
console.log(car1)
/*
{
color: "black"
make: "Eagle"
model: "Talon TSi"
owner: {
age: 33
name: "Rand McKinnon"
sex: "M"
}
year: 1993
}
*/
| | —- |
object构造函数
| 【示例】```javascript var wcDog =new Object(); wcDog.name=”旺财”; wcDog.age=3; wcDog.work=function(){ alert(“我是”+wcDog.name+”,汪汪汪……”); } wcDog.work();
|
| --- |
<a name="yqJdx"></a>
#### 工厂模式
| 【示例】```javascript
function createObj(name, age) {
let obj = new Object();
obj.name = name;
obj.age = age;
obj.sayHi = function() {
console.log(obj.name);
}
return obj;
}
let dog = createObj('汪汪', 20);
console.log(dog.age); // 20
dog.sayHi(); // '汪汪'
| | —- |
原型方式
| 【示例】```javascript function Dog(){
} Dog.prototype.name=”旺财”; Dog.prototype.eat=function(){ alert(this.name+”是个吃货”); } var wangcai =new Dog(); wangcai.eat();
|
| --- |
<a name="TOH2Z"></a>
#### 混合方式(原型+构造函数)
| 【示例】```javascript
function Graph() {
this.vertices = [];
this.edges = [];
}
Graph.prototype = {
addVertex: function(v){
this.vertices.push(v);
}
};
var g = new Graph();
// g 是生成的对象,他的自身属性有 'vertices' 和 'edges'。
// 在 g 被实例化时,g.[[Prototype]] 指向了 Graph.prototype。
| | —- |
动态原型(混合模式的一种特例)
| 【示例】```javascript function Animal(name, age) { this.name = name; this.age = age; if (typeof Animal.sell === ‘undefined’) { Animal.prototype.sell = function() { alert(‘我是’ + this.name + ‘今年’ + this.age + ‘岁了,汪汪~’); } Animal.sell = true; } } var dog = new Animal(‘狗狗’, age) dog.sell()
|
| --- |
<a name="233bd7f1219ea2ad84e218e29cbc301b"></a>
### 对象属性索引
一、通过构造函数创建一个对象,如果最初使用名称定义了一个属性,则必须通过名称来访问它;如果最初使用序号来定义一个属性,则必须通过索引来访问它。
| 【示例】```javascript
myCar.color = 'red'
console.log(myCar.color) // 'red'
myCar[5] = '25'
console.log(myCar[5]) // '25'
console.log(myCar)
| | —- |
1、这条规则的例外是从与HTML对应的对象,如forms数组。这些数组的元素,可以通过其序号(依据其在文档中出现的顺序),也可以按照其名称访问它。
| 【示例】文档中的第二个