JavaScript对象入门

对象基础

对象是一个包含相关数据和方法的集合(通常由一些变量和函数组成,我们称之为对象里面的属性和方法
如同Javascript中的很多东西一样,创建一个对象通常先定义初始化变量。 尝试在您已有的文件中JavaScript代码下面输入以下内容, 保存刷新页面:

var person = {};

如果你在浏览器控制台输入person,然后按下Enter(确认)键,你会得到如下结果:

[object Object]

这是一个空对象,所以我们做不了更多的事情,创建一个更加复杂的对象吧!

var person = {
  name : ['Bob', 'Smith'],
  age : 32,
  gender : 'male',
  interests : ['music', 'skiing'],
  bio : function() {
    alert(this.name[0] + ' ' + this.name[1] + ' is ' + this.age + ' years old. He likes ' + this.interests[0] + ' and ' + this.interests[1] + '.');
  },
  greeting: function() {
    alert('Hi! I\'m ' + this.name[0] + '.');
  }
};


person.name[0]
person.age
person.interests[1]
person.bio()
person.greeting()

一个对象由许多的成员组成,每一个成员都拥有一个名字(像上面的name、age),和一个值(如[‘Bob’, ‘Smith’]、32)。每一个名字/值(name/value)对被逗号分隔开,并且名字和值之间由冒号(:)分隔,语法规则如下所示:

var objectName = {
member1Name : member1Value,
member2Name : member2Value,
member3Name : member3Value
}

对象成员的值可以是任意的,在我们的person对象里有字符串(string),数字(number),两个数组(array),两个函数(function)。前4个成员是资料项目,被称为对象的属性(property),后两个成员是函数,允许对象对资料做一些操作,被称为对象的方法(method)

当你想要传输一些有结构和关联的资料时常见的方式是使用字面量来创建一个对象,举例来说,发起一个请求到服务器以存储一些数据到数据库,发送一个对象要比分别发送这些数据更有效率,而且比起数组更为易用,因为你使用名字(name)来标识这些资料。


点表示法

在上面的例子中,你使用了点表示法(dot notation)来访问对象的属性和方法。对象的名字表现为一个命名空间(namespace),它必须写在第一位——当你想访问对象内部的属性或方法时,然后是一个点(.),紧接着是你想要访问的项目,标识可以是简单属性的名字(name),或者是数组属性的一个子元素,又或者是对象的方法调用。如下所示:

自命名空间

可以用一个对象来做另一个对象成员的值。例如将name成员

name : [‘Bob’, ‘Smith’],
name : {
first : ‘Bob’,
last : ‘Smith’
},

括号表示法

另外一种访问属性的方式是使用括号表示法(bracket notation),替代这样的代码

person.age
person.name.first

person[‘age’]
person[‘name’][‘first’]

这看起来很像访问一个数组的元素,从根本上来说是一回事儿,你使用了关联了值的名字,而不是索引去选择元素。难怪对象有时被称之为关联数组(associative array)了——对象做了字符串到值的映射,而数组做的是数字到值的映射。


设置对象成员

目前我们仅仅看到了如何访问对象的成员,而你其实也可以设置对象成员的值,通过声明你要设置的成员,像这样

person[‘name’][‘last’] = ‘Cratchit’
设置成员并不意味着你只能更新已经存在的属性的值,你完全可以创建新的成员,尝试以下代码:

person[‘eyes’] = ‘hazel’
person.farewell = function() { alert(“Bye everybody!”) }

现在你可以测试你新创建的成员

person[‘eyes’]
person.farewell()


this的含义

看这个例子:

greeting: function() {
alert('Hi! I’m ’ + this.name.first + ‘.’);
}

你也许想知道"this"是什么,关键字"this"指向了当前代码运行时的对象( 原文:the current object the code is being written inside )——这里即指person对象,为什么不直接写person呢?
两个简单的person的对象来说明:

var person1 = {
name : ‘Chris’,
greeting: function() {
alert('Hi! I’m ’ + this.name + ‘.’);
}
}

var person2 = {
name : ‘Brian’,
greeting: function() {
alert('Hi! I’m ’ + this.name + ‘.’);
}
}

在这里,person1.greeting()会输出:“Hi! I’m Chris.”;person2.greeting()会输出:“Hi! I’m Brain.”,即使greeting这个方法的代码是一样的。就像我们之前说的,this 指向了代码所在的对象(其实代码运行时所在的对象)。在字面量的对象里this看起来不是很有用,但是当你动态创建一个对象(例如使用构造器)时它是非常有用的,之后你会更清楚它的用途


从零开始面向对象的程序设计

首先, 让我们给您定义一个面向对象的程序(OOP) 的极其简单的概念. 我们说的极其简单, 是因为 OOP 很快就变得非常复杂,如果现在给您一个完整的定义可能会让您产生迷惑而非帮助. 最基本的 OOP 思想就是我们想要在我们的程序中使用对象来表示现实世界模型, 并提供一个简单的方式来访问它的功能,否则很难甚至不能实现.

对象可以包含相关的数据和代码,这些代表现实世界模型的一些信息或者功能,或者它特有的一些行为. 对象数据(也经常称为函数) 可以有结构的存储 (官方术语为 封装) 在对象包内 (也可以给一个特殊的名字来表示,有时候也叫做命名空间), 可以使它容易组织和访问; 对象也通常用于存储数据,这样就可以很容易的在网络上传输.

定义一个对象模板

让我们来考虑一个简单的程序,它可以显示一个学校的学生和老师的信息.在这里我们不讨论任何程序语言,我们只讨论 OOP 思想.

首先,我们可以回到上一节拿到定义好属性和方法的Person对象。对于一个人(person)来说,我们能在他们身上获取到很多信息(他们的住址,身高,鞋码,基因图谱,护照信息,显著的性格特征等等),然而,我们仅仅需要他们的名字,年龄,性别,兴趣 这些信息,然后,我们会基于他们的这些信息写一个简短的介绍关于他们自己,在最后我们还需要教会他们打招呼。以上的方式被称为抽象-为了我们编程的目标而利用事物的一些重要特性去把复杂的事物简单化

在这里插入图片描述
在一些面向对象的语言中,我们用类(class)的概念去描述一个对象(您在下面就能看到JavaScript使用了一个完全不同的术语)-类并不完全是一个对象,它更像是一个定义对象特质的模板

老师和学生具有一些相同的特征比如姓名、性别、年龄,因此只需要定义这些特征一次就可以了。您可以在不同的类里分开定义这些相同的特征,这样该特征会有一个不同的命名空间。比如,一个学生的 greeting 可以是 “Yo, I’m [firstName]” (例子 Yo, I’m Sam),老师的可能会正式一些,比如"Hello, my name is [Prefix] [lastName]" (例子 Hello, My name is Mr Griffiths)。


构建函数和对象示例

有些人认为 JavaScript 不是真正的面向对象的语言,比如它没有像许多面向对象的语言一样有用于创建class类的声明。JavaScript 用一种称为构建函数的特殊函数来定义对象和它们的特征。构建函数非常有用,因为很多情况下您不知道实际需要多少个对象(实例)。构建函数提供了创建您所需对象(实例)的有效方法,将对象的数据和特征函数按需联结至相应对象。

不像“经典”的面向对象的语言,从构建函数创建的新实例的特征并非全盘复制,而是通过一个叫做原形链的参考链链接过去的

一个简单的例子

function createNewPerson(name) {
var obj = {};
obj.name = name;
obj.greeting = function () {
alert('Hi! I’m ’ + this.name + ‘.’);
}
return obj;
}

avaScript 通过构建函数提供了一个便捷的方法,方法如下:

function Person(name) {
this.name = name;
this.greeting = function() {
alert('Hi! I’m ’ + this.name + ‘.’);
};
}

这个构建函数是 JavaScript 版本的类。您会发现,它只定义了对象的属性和方法,除了没有明确创建一个对象和返回任何值和之外,它有了您期待的函数所拥有的全部功能。这里使用了this关键词,即无论是该对象的哪个实例被这个构建函数创建,它的 name 属性就是传递到构建函数形参name的值,它的 greeting() 方法中也将使用相同的传递到构建函数形参name的值。

那如何调用构建函数创建新的实例呢?

var person1 = new Person(‘Bob’);
var person2 = new Person(‘Sarah’);
//保存并刷新浏览器,在 console 里输入如下代码:
person1.name
person1.greeting()
person2.name
person2.greeting()

酷!您现在看到页面上有两个对象,每一个保存在不同的命名空间里,当您访问它们的属性和方法时,您需要使用person1或者person2来调用它们。尽管它们有着相同的name属性和 greeting()方法它们是各自独立的,所以相互的功能不会冲突。注意它们使用的是自己的 name 值,这也是使用 this 关键字的原因,它们使用的从实参传入形参的自己的值,而不是其它的什么值。
ps:this 的意思是自己对象本身

var person1 = new Person(‘Bob’);
var person2 = new Person(‘Sarah’);

关键字 new 跟着一个含参函数,用于告知浏览器我们想要创建一个对象实例,非常类似函数调用,并把结果保存到变量中。每个示例类都是根据下面的方式定义的。

function Person(name) {
this.name = name;
this.greeting = function() {
alert('Hi! I’m ’ + this.name + ‘.’);
};
}

当新的对象被创立, 变量person1与person2有效地包含了以下值:

{
name : ‘Bob’,
greeting : function() {
alert('Hi! I’m ’ + this.name + ‘.’);
}
}
{
name : ‘Sarah’,
greeting : function() {
alert('Hi! I’m ’ + this.name + ‘.’);
}
}


创建我们最终的构造函数

移除掉您之前写的所有代码, 用如下构造函数替代 —— 实现原理上,这与我们之前的例子并无二致, 只是变得稍稍复杂了些:

function Person(first, last, age, gender, interests) {
this.name = {
first,
last
};
this.age = age;
this.gender = gender;
this.interests = interests;
this.bio = function() {
alert(this.name.first + ’ ’ + this.name.last + ’ is ’ + this.age + ’ years old. He likes ’ + this.interests[0] + ’ and ’ + this.interests[1] + ‘.’);
};
this.greeting = function() {
alert('Hi! I’m ’ + this.name.first + ‘.’);
};
};
var person1 = new Person(‘Bob’, ‘Smith’, 32, ‘male’, [‘music’, ‘skiing’]);

创建对象实例的其他方式

object()构造函数

var person1 = new Object():
//这样就在person1变量中存储了一个空对象。然后, 可以根据需要, 使用点或括号表示法向此对象添加属性和方法;试试这个例子:
person1.name = ‘Chris’;
person1[‘age’] = 38;
person1.greeting = function() {
alert('Hi! I’m ’ + this.name + ‘.’);
}
var person1 = new Object({
name : ‘Chris’,
age : 38,
greeting : function() {
alert('Hi! I’m ’ + this.name + ‘.’);
}
});


使用create()方法

JavaScript有个内嵌的方法create(), 它允许您基于现有对象创建新的对象实例。

这里是引用
var person2 = Object.create(person1);
现在尝试这个:
person2.name
person2.greeting()

您可以看到,person2是基于person1创建的, 它们具有相同的属性和方法。这非常有用, 因为它允许您创建新的对象实例而无需定义构造函数。缺点是比起构造函数,浏览器在更晚的时候才支持create()方法(IE9, IE8 或甚至以前相比), 加上一些人认为构造函数让您的代码看上去更整洁 —— 您可以在一个地方创建您的构造函数, 然后根据需要创建实例, 这让您能很清楚地知道它们来自哪里。


对象原型 -基于原型的语言?

JavaScript 常被描述为一种基于原型的语言 (prototype-based language)——每个对象拥有一个原型对象,对象以其原型为模板、从原型继承方法和属性。原型对象也可能拥有原型,并从中继承方法和属性,一层一层、以此类推。这种关系常被称为原型链 (prototype chain),它解释了为何一个对象会拥有定义在其他对象中的属性和方法。
准确地说,这些属性和方法定义在Object的构造器函数(constructor functions)之上的prototype属性上,而非对象实例本身。

在传统的 OOP 中,首先定义“类”,此后创建对象实例时,类中定义的所有属性和方法都被复制到实例中。在 JavaScript 中并不如此复制——而是在对象实例和它的构造器之间建立一个链接(它是__proto__属性,是从构造函数的prototype属性派生的),之后通过上溯原型链,在构造器中找到这些属性和方法。


使用JavaScript中的原型

在javascript中,函数可以有属性。 每个函数都有一个特殊的属性叫作原型(prototype) ,正如下面所展示的。请注意,下面的代码是独立的一段(在网页中没有其他代码的情况下,这段代码是安全的)。为了最好的学习体验,你最好打开一个控制台 (在Chrome和Firefox中,可以按Ctrl+Shift+I来打开)切换到"控制台" 选项卡, 复制粘贴下面的JavaScript代码,然后按回车来运行.

function doSomething(){}
console.log( doSomething.prototype );
// It does not matter how you declare the function, a
// function in javascript will always have a default
// prototype property.
var doSomething = function(){};
console.log( doSomething.prototype );

doSomething 函数有一个默认的原型属性,它在控制台上面呈现了出来. 运行这段代码之后,控制台上面应该出现了像这样的一个对象

{
constructor: ƒ doSomething(),
proto: {
constructor: ƒ Object(),
hasOwnProperty: ƒ hasOwnProperty(),
isPrototypeOf: ƒ isPrototypeOf(),
propertyIsEnumerable: ƒ propertyIsEnumerable(),
toLocaleString: ƒ toLocaleString(),
toString: ƒ toString(),
valueOf: ƒ valueOf()
}
}

创建一个实例

var doSomeInstancing = new doSomething();
doSomeInstancing.prop = “some value”; // add a property onto the object
console.log( doSomeInstancing );

就像上面看到的, doSomeInstancing 的 proto 属性就是doSomething.prototype. 但是这又有什么用呢? 好吧,当你访问 doSomeInstancing 的一个属性, 浏览器首先查找 doSomeInstancing 是否有这个属性. 如果 doSomeInstancing 没有这个属性, 然后浏览器就会在 doSomeInstancing 的 proto 中查找这个属性(也就是 doSomething.prototype). 如果 doSomeInstancing 的 proto 有这个属性, 那么 doSomeInstancing 的 proto 上的这个属性就会被使用. 否则, 如果 doSomeInstancing 的 proto 没有这个属性, 浏览器就会去查找 doSomeInstancing 的 protoproto ,看它是否有这个属性. 默认情况下, 所有函数的原型属性的 proto 就是 window.Object.prototype. 所以 doSomeInstancing 的 protoproto (也就是 doSomething.prototype 的 proto (也就是 Object.prototype)) 会被查找是否有这个属性. 如果没有在它里面找到这个属性, 然后就会在 doSomeInstancing 的 protoprotoproto 里面查找. 然而这有一个问题: doSomeInstancing 的 protoprotoproto 不存在. 最后, 原型链上面的所有的 proto 都被找完了, 浏览器所有已经声明了的 proto 上都不存在这个属性,然后就得出结论,这个属性是 undefined.


理解原型对象

function Person(first, last, age, gender, interests) {

// 属性与方法定义

};

创建一个对象实例

var person1 = new Person(‘Bob’, ‘Smith’, 32, ‘male’, [‘music’, ‘skiing’]);

在这里插入图片描述
那么,调用 person1 的“实际定义在 Object 上”的方法时,会发生什么?比如:

person1.valueof();

这个方法仅仅返回了被调用对象的值。在这个例子中发生了如下过程:

浏览器首先检查,person1 对象是否具有可用的 valueOf() 方法。
如果没有,则浏览器检查 person1 对象的原型对象(即 Person构造函数的prototype属性所指向的对象)是否具有可用的 valueof() 方法。
如果也没有,则浏览器检查 Person() 构造函数的prototype属性所指向的对象的原型对象(即 Object构造函数的prototype属性所指向的对象)是否具有可用的 valueOf() 方法。这里有这个方法,于是该方法被调用。

注意:必须重申,原型链中的方法和属性没有被复制到其他对象——它们被访问需要通过前面所说的“原型链”的方式。没有官方的方法用于直接访问一个对象的原型对象——原型链中的“连接”被定义在一个内部属性中,在 JavaScript 语言标准中用 [[prototype]] 表示(参见 ECMAScript)。然而,大多数现代浏览器还是提供了一个名为 proto (前后各有2个下划线)的属性,其包含了对象的原型。你可以尝试输入 person1.proto 和 person1.proto.proto,看看代码中的原型链是什么样的!

prototype属性:继承成员被定义的地方

那么,那些继承的属性和方法在哪儿定义呢?如果你查看 Object 参考页,会发现左侧列出许多属性和方法——大大超过我们在 person1 对象中看到的继承成员的数量。某些属性或方法被继承了,而另一些没有——为什么呢?

原因在于,继承的属性和方法是定义在 prototype 属性之上的(你可以称之为子命名空间 (sub namespace) )——那些以 Object.prototype. 开头的属性,而非仅仅以 Object. 开头的属性。prototype 属性的值是一个对象,我们希望被原型链下游的对象继承的属性和方法,都被储存在其中。

于是 Object.prototype.watch()、Object.prototype.valueOf() 等等成员,适用于任何继承自 Object() 的对象类型,包括使用构造器创建的新的对象实例。

Object.is()、Object.keys(),以及其他不在 prototype 对象内的成员,不会被“对象实例”或“继承自 Object() 的对象类型”所继承。这些方法/属性仅能被 Object() 构造器自身使用。
JavaScript 中到处都是通过原型链继承的例子。比如,你可以尝试从 String、Date、Number 和 Array 全局对象的原型中寻找方法和属性。它们都在原型上定义了一些方法,因此当你创建一个字符串时:

prototype 属性大概是 JavaScript 中最容易混淆的名称之一。你可能会认为,this 关键字指向当前对象的原型对象,其实不是(还记得么?原型对象是一个内部对象,应当使用 proto 访问)。prototype 属性包含(指向)一个对象,你在这个对象中定义需要被继承的成员

ps:这里的prototype属性是原型对象,,包含自己的所有的属性与方法,在这里定义自己的可继承的属性与方法,__proto__则是指向当前对象的原型对象

在这里插入图片描述在这里插入图片描述


create()

我们曾经讲过如何用 Object.create() 方法创建新的对象实例。

例如,在上个例子的 JavaScript 控制台中输入:
var person2 = Object.create(person1);
create() 实际做的是从指定原型对象创建一个新的对象。这里以 person1 为原型对象创建了 person2 对象。在控制台输入:
person2.proto
结果返回对象person1。


constructior 属性

每个实例对象都从原型中继承了一个constructor属性,该属性指向了用于构造此实例对象的构造函数。

person1.constructor
person2.constructor

都将返回 Person() 构造器,因为该构造器包含这些实例的原始定义。


修改原型

这段代码将为构造器的 prototype 属性添加一个新的方法:

Person.prototype.farewell = function() {
alert(this.name.first + ’ has left the building. Bye for now!’);
}
person1.farewell();

我们的代码中定义了构造器,然后用这个构造器创建了一个对象实例,此后向构造器的 prototype 添加了一个新的方法:

function Person(first, last, age, gender, interests) {

// 属性与方法定义

};

var person1 = new Person(‘Tammi’, ‘Smith’, 32, ‘neutral’, [‘music’, ‘skiing’, ‘kickboxing’]);

Person.prototype.farewell = function() {
alert(this.name.first + ’ has left the building. Bye for now!’);
}

但是 farewell() 方法仍然可用于 person1 对象实例——旧有对象实例的可用功能被自动更新了。这证明了先前描述的原型链模型。这种继承模型下,上游对象的方法不会复制到下游的对象实例中;下游对象本身虽然没有定义这些方法,但浏览器会通过上溯原型链、从上游对象中找到它们。这种继承模型提供了一个强大而可扩展的功能系统。

事实上,一种极其常见的对象定义模式是,在构造器(函数体)中定义属性、在 prototype 属性上定义方法。如此,构造器只包含属性定义,而方法则分装在不同的代码块,代码更具可读性。例如:

// 构造器及其属性定义

function Test(a,b,c,d) {
  // 属性定义
};

// 定义第一个方法

Test.prototype.x = function () { ... }

// 定义第二个方法

Test.prototype.y = function () { ... }

// 等等……

javascript 中的继承

定义 Teacher() 构造器函数

function Teacher(first, last, age, gender, interests, subject) {
Person.call(this, first, last, age, gender, interests);

this.subject = subject;
}

这在很多方面看起来都和Person的构造器很像,但是这里有一些我们从没见过的奇怪玩意——call()函数。基本上,这个函数允许您调用一个在这个文件里别处定义的函数。第一个参数指明了在您运行这个函数时想对“this”指定的值,也就是说,您可以重新指定您调用的函数里所有“this”指向的对象。其他的变量指明了所有目标函数运行时接受的参数。

所以在这个例子里,我们很有效的在Teacher()构造函数里运行了Person()构造函数(见上文),得到了和在Teacher()里定义的一样的属性,但是用的是传送给Teacher(),而不是Person()的值(我们简单使用这里的this作为传给call()的this,意味着this指向Teacher()函数)。
在构造器里的最后一行代码简单地定义了一个新的subject属性,这将是教师会有的,而一般人没有的属性。

从无参构造函数继承

请注意,如果您继承的构造函数不从传入的参数中获取其属性值,则不需要在call()中为其指定其他参数。所以,例如,如果您有一些相当简单的东西:

function Brick() {
this.width = 10;
this.height = 20;
}

可以这样继承width和height属性:

function BlueGlassBrick() {
Brick.call(this);

this.opacity = 0.5;
this.color = ‘blue’;
}

设置 Teacher() 的原型和构造器引用

到目前为止一切看起来都还行,但是我们遇到问题了。我们已经定义了一个新的构造器,这个构造器默认有一个空的原型属性。我们需要让Teacher()从Person()的原型对象里继承方法。我们要怎么做呢?

Teacher.prototype = Object.create(Person.prototype);

这里我们的老朋友create()又来帮忙了——在这个例子里我们用这个函数来创建一个和Person.prototype一样的新的原型属性值(这个属性指向一个包括属性和方法的对象),然后将其作为Teacher.prototype的属性值。这意味着Teacher.prototype现在会继承Person.prototype的所有属性和方法。
接下来,在我们动工之前,还需要完成一件事 — 现在Teacher()的prototype的constructor属性指向的是Person(), 这是由我们生成Teacher()的方式决定的。(这篇 Stack Overflow post 文章会告诉您详细的原理) — 将您写的页面在浏览器中打开,进入JavaScript控制台,输入以下代码来确认:

Teacher.prototype.constructor
Teacher.prototype.constructor = Teacher;

当您保存并刷新页面以后,输入Teacher.prototype.constructor就会得到Teacher()。

向 Teacher() 添加一个新的greeting()函数

为了完善代码,您还需在构造函数Teacher()上定义一个新的函数greeting()。最简单的方法是在Teacher的原型上定义它—把以下代码添加到您代码的底部:

Teacher.prototype.greeting = function() {
}

对象成员总结

总结一下,您应该基本了解了以下三种属性或者方法:

那些定义在构造器函数中的、用于给予对象实例的。这些都很容易发现 - 在您自己的代码中,它们是构造函数中使用this.x = x类型的行;在内置的浏览器代码中,它们是可用于对象实例的成员(通常通过使用new关键字调用构造函数来创建,例如var myInstance = new myConstructor())。
那些直接在构造函数上定义、仅在构造函数上可用的。这些通常仅在内置的浏览器对象中可用,并通过被直接链接到构造函数而不是实例来识别。 例如Object.keys()。
那些在构造函数原型上定义、由所有实例和对象类继承的。这些包括在构造函数的原型属性上定义的任何成员,如myConstructor.prototype.x()。


何时在 JavaScript 中使用继承?

在某种程度上来说,您一直都在使用继承 - 无论您是使用WebAPI的不同特性还是调用字符串、数组等浏览器内置对象的方法和属性的时候,您都在隐式地使用继承。

就在自己代码中使用继承而言,您可能不会使用的非常频繁,特别是在小型项目中或者刚开始学习时 - 因为当您不需要对象和继承的时候,仅仅为了使用而使用它们只是在浪费时间而已。但是随着您的代码量的增大,您会越来越发现它的必要性。如果您开始创建一系列拥有相似特性的对象时,那么创建一个包含所有共有功能的通用对象,然后在更特殊的对象类型中继承这些特性,将会变得更加方便有用。

注: 考虑到JavaScript的工作方式,由于原型链等特性的存在,在不同对象之间功能的共享通常被叫做 委托 - 特殊的对象将功能委托给通用的对象类型完成。这也许比将其称之为继承更为贴切,因为“被继承”了的功能并没有被拷贝到正在“进行继承”的对象中,相反它仍存在于通用的对象中。
之,对象是另一种形式的代码重用,就像函数和循环一样,有他们特定的角色和优点。如果您发现自己创建了一堆相关的变量和函数,还想一起追踪它们并将其灵活打包的话,对象是个不错的主意。对象在您打算把一个数据集合从一个地方传递到另一个地方的时候非常有用。这些都可以在不使用构造器和继承的情况下完成。如果您只是需要一个单一的对象实例,也许使用对象常量会好些,您当然不需要使用继承。


使用json资料

avaScript对象表示法(JSON)是用于将结构化数据表示为JavaScript对象的标准格式,通常用于在网站上表示和传输数据(例如从服务器向客户端发送一些数据,因此可以将其显示在网页上)。您会经常遇到它,所以在本文中,我们向您提供使用JavaScript处理JSON的所有工作,包括访问JSON对象中的数据项并编写自己的JSON。

什么是 JSON?

它是基于 JavaScript 语法,但它独立于JavaScript
JSON可以作为一个对象或者字符串存在,前者用于解读 JSON 中的数据,后者用于通过网络传输 JSON 数据。 这不是一个大事件——JavaScript 提供一个全局的 可访问的 JSON 对象来对这两种数据进行转换。
在这里插入图片描述
为了访问对象中的对象,您只需简单地链式访问(通过属性名和数组索引)。例如,访问 superHeroes 对象中的 members 数组对象的第二个元素的 powers 数组对象的第三个元素,您可以这样做:

superHeroes[“members”][1][“powers”][2]
首先我们有变量名 superHeroes,储存对象 。
在对象中我们想访问 members 属性,所以我们使用 [“members”]。
members 包含有对象数组,我们想要访问第二个元素,所以我们使用[1]。
在对象内,我们想访问 powers 属性,所以我们使用 [“powers”]。
powers 属性是一个包含英雄技能的数组。我们想要第三个,所以我们使用[2]

json数组

前面我们已经说过,”我们已经可以推测出 JSON 对象就是基于 JavaScript 对象,而且这几乎是正确的“——我们说几乎正确的原因是数组对象也是一种合法的 JSON 对象,例如:

[
{
“name” : “Molecule Man”,
“age” : 29,
“secretIdentity” : “Dan Jukes”,
“powers” : [
“Radiation resistance”,
“Turning tiny”,
“Radiation blast”
]
},
{
“name” : “Madame Uppercut”,
“age” : 39,
“secretIdentity” : “Jane Wilson”,
“powers” : [
“Million tonne punch”,
“Damage resistance”,
“Superhuman reflexes”
]
}
]

上面是完全合法的 JSON。您只需要通过数组索引就可以访问数组元素,如[0][“powers”][0]。

其他注意

JSON 是一种纯数据格式,它只包含属性,没有方法。
JSON 要求有两头的 { } 来使其合法。最安全的写法是有两边的括号,而不是一边。
甚至一个错位的逗号或分号就可以导致 JSON 文件出错。您应该小心的检查您想使用的数据(虽然计算机生成的 JSON 很少出错,只要生成程序正常工作)。您可以通过像 JSONLint 的应用程序来检验 JSON。
JSON 可以将任何标准合法的 JSON 数据格式化保存,不只是数组和对象。比如,一个单一的字符串或者数字可以是合法的 JSON 对象。虽然不是特别有用处……
不像 JavaScript 标识符可以用作属性,在 JSON 中,只有字符串才能用作属性

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值