使用对象
一个对象就是一系列属性的集合,一个属性包含一个名和一个值。一个属性的值可以是函数,这种情况下属性也被称为方法。
对象和属性
一个对象的属性可以被解释成一个附加到对象上的变量。可以通过点符号来访问一个对象的属性。
objectName.propertyName
var myCar = new Object();
myCar.make = "Ford";
JavaScript 对象的属性也可以通过方括号访问或者设置,对象有时也被叫作关联数组,因为每个属性都有一个用于访问它的字符串值
myCar["make"] = "Ford";
person['name']['last'] = 'Cratchit'
在 for...in 语句中使用方括号标记以枚举一个对象的所有属性。
for (var i in obj) {
if (obj.hasOwnProperty(i)) {
result += objName + "." + i + " = " + obj[i] + "\n";
}
}
枚举一个对象中的所有属性的方法:
- for...in 循环 该方法依次访问一个对象及其原型链中所有可枚举的属性。
- Object.keys(o) 该方法返回对象
o自身包含(不包括原型中)的所有可枚举属性的名称的数组。 - Object.getOwnPropertyNames(o) 该方法返回对象
o自身包含(不包括原型中)的所有属性 (无论是否可枚举) 的名称的数组。
创建新对象
可以通过对象初始化器(Object Initializer)创建对象。或者可以创建一个构造函数并使用该函数和 new 操作符初始化对象。
- 对象初始化器
var obj = { property_1: value_1, // property_# 可以是一个标识符...
2: value_2, // 或一个数字...
}
- 构造函数
- 通过创建一个构造函数来定义对象的类型。首字母大写是非常普遍而且很恰当的惯用法。
- 通过
new创建对象实例。
function Car(make, model, year) {
this.make = make;
this.model = model;
this.year = year;
}
通过使用 this 将传入函数的值赋给对象的属性。
var mycar = new Car("Eagle", "Talon TSi", 1993);
- Object.create方法
允许为创建的对象选择一个原型对象,而不用定义构造函数。
// 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
继承
所有的 JavaScript 对象至少继承于一个对象。被继承的对象被称作原型,并且继承的属性可通过构造函数的 prototype 对象找到。
为对象类型定义属性: 可通过prototype为之前定义的对象类型增加属性。
Car.prototype.color = null;
car1.color = 'red';
当谈到继承时,JavaScript 只有一种结构:对象。每个实例对象(object)都有一个私有属性(称之为 proto )指向它的构造函数的原型对象(prototype)。该原型对象也有一个自己的原型对象(proto),层层向上直到一个对象的原型对象为 null。根据定义,null 没有原型,并作为这个原型链中的最后一个环节。
基于原型链的继承
someObject.[[Prototype]] 符号是用于指向 someObject 的原型。从 ECMAScript 6 开始,[[Prototype]] 可以通过 Object.getPrototypeOf() 和 Object.setPrototypeOf() 访问器来访问。这个等同于 JavaScript 的非标准但许多浏览器实现的属性 proto。Object.prototype表示Object的原型对象
this 指向的是当前继承的对象,而不是继承的函数所在的原型对象。函数(function)是允许拥有属性的。所有的函数会有一个特别的属性 —— prototype
创建对象
- 使用语法结构
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
- 使用构造器
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。
- 使用Object.create 新对象的原型就是调用 create 方法时传入的第一个参数:
var a = {a: 1};
// a ---> Object.prototype ---> null
var b = Object.create(a);
// b ---> a ---> Object.prototype ---> null
console.log(b.a); // 1 (继承而来)
var c = Object.create(b);
// c ---> b ---> a ---> Object.prototype ---> null
var d = Object.create(null);
// d ---> null
console.log(d.hasOwnProperty); // undefined,因为 d 没有继承 Object.prototype
- 使用class
class Polygon {
constructor(height, width) {
this.height = height;
this.width = width;
}
}
class Square extends Polygon {
constructor(sideLength) {
super(sideLength, sideLength);
}
get area() {
return this.height * this.width;
}
set sideLength(newLength) {
this.height = newLength;
this.width = newLength;
}
}
var square = new Square(2);
hasOwnProperty 是 JavaScript 中唯一一个处理属性并且不会遍历原型链的方法。
console.log(g.hasOwnProperty('nope'));
constructor属性
每个实例对象都从原型中继承了一个 constructor 属性,该属性指向了用于构造此实例对象的构造函数。
var person3 = new person1.constructor('Karen', 'Stephenson', 26, 'female', ['playing drums', 'mountain climbing']);
修改构造器的 prototype 属性
function Ball(x, y, velX, velY, exists, color, size){
Shape.call(this, x, y, velX, velY, exists);//构造器 `Ball()` 应该从构造器 `Shape()` 继承 `x`, `y`, `velX`, `velY`,和 `exists` 属性
this.color = color;
this.size = size;
}
Ball.prototype = Object.create(Shape.prototype);
Ball.prototype.constructor = Ball;//给构造器 `Ball()` 的`prototype` 和 `constructor` 属性设置适当的值。
function EviCircle(x, y, exists){
Shape.call(this, x, y, 20, 20, exists);
this.color = 'white';
this.size = 10;
}
EviCircle.prototype = Object.create(Shape.prototype);
EviCircle.prototype.constructor = EviCircle;
定义方法
通过this引用对象
定义getters与setters
一个getter是一个获取某个特定属性的值的方法。一个 setter 是一个设定某个属性的值的方法。你可以为预定义的或用户定义的对象定义 getter 和 setter 以支持新增的属性。定义 getter 和 setter 的语法采用对象字面量语法。
var o = {
a: 7,
get b() { return this.a + 1; },
set c(x) { this.a = x / 2; }
};
删除属性
可以用delete操作符删除一个不是继承而来的属性。
如果一个全局变量不是用 var 关键字声明的话,也可以用 delete 删除它
在 JavaScript 中 objects 是一种引用类型。两个独立声明的对象永远也不会相等,即使他们有相同的属性,只有在比较一个对象和这个对象的引用时,才会返回 true.
类
class Person {
name;
constructor(name) {
this.name = name;
}
introduceSelf() {
console.log(`Hi! I'm ${this.name}`);
}
}
构造函数使用 constructor 关键字来声明。就像在类声明外的构造函数一样,不需要任何特殊的初始化内容,你可以省略构造函数,默认的构造函数会被自动生成。会:
- 创建一个新的对象
- 将
this绑定到这个新的对象,你可以在构造函数代码中使用this来引用它 - 执行构造函数中的代码
- 返回这个新的对象
const giles = new Person('Giles');
giles.introduceSelf(); // Hi! I'm Giles
继承
声明子类:使用 extends 关键字来声明这个类继承自另一个类。
class Professor extends Person {
teaches;
constructor(name, teaches) {
super(name);
this.teaches = teaches;
}
}
构造函数中需要做的第一件事是使用 super() 调用父类的构造函数,并传递 name 参数。父类的构造函数会设置 name 属性。
封装
类私有域
类属性在默认情况下是公有的,但可以使用增加哈希前缀 # 的方法来定义私有类字段
class ClassWithPrivateField {
#privateField;
}
class ClassWithPrivateMethod {
#privateMethod() {
return 'hello world';
}
}
class ClassWithPrivateStaticField {
static #PRIVATE_STATIC_FIELD;
}
从作用域之外引用 # 名称、内部在未声明的情况下引用私有字段、或尝试使用 delete 移除声明的字段都会抛出语法错误。
私有方法
class Example {
somePublicMethod() {
this.#somePrivateMethod();
}
#somePrivateMethod() {
console.log('You called me?');
}
}
JSON
JavaScript 对象表示法(JSON)是用于将结构化数据表示为 JavaScript 对象的标准格式,通常用于在网站上表示和传输数据。JSON 可以作为一个对象或者字符串存在,前者用于解读 JSON 中的数据,后者用于通过网络传输 JSON 数据。一个 JSON 对象可以被储存在它自己的文件中,这基本上就是一个文本文件,扩展名为 .json
JSON结构
JSON 对象就是基于 JavaScript 对象,可以把 JavaScript 对象原原本本的写入 JSON 数据——字符串,数字,数组,布尔还有其它的字面值对象
{
"squadName" : "Super hero squad",
"homeTown" : "Metro City",
"formed" : 2016,
"secretBase" : "Super tower",
"active" : true,
"members" : [
{
"name" : "Molecule Man",
"age" : 29,
"secretIdentity" : "Dan Jukes",
"powers" : [
"Radiation resistance",
"Turning tiny",
"Radiation blast"
]
}
}
为了访问对象中的对象,只需简单地链式访问
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 是一种纯数据格式,它只包含属性,没有方法。
- JSON 要求在字符串和属性名称周围使用双引号。单引号无效。
- 甚至一个错位的逗号或分号就可以导致 JSON 文件出错。
加载JSON
为了载入 JSON 到页面中,使用一个名为XMLHTTPRequest的 API(常称为 XHR)。是一个JavaScript 对象,能够通过代码来向服务器请求资源文件 (如:图片,文本,JSON,甚至 HTML 片段),意味着可以更新小段内容而不用重新加载整个页面
<body>
<header>
</header>
<section>
</section>
<script>
var header = document.querySelector('header');
var section = document.querySelector('section');
var requestURL = 'https://mdn.github.io/learning-area/javascript/oojs/json/superheroes.json';//保存一个即将访问的 URL 作为变量
var request = new XMLHttpRequest();//创建一个 HTTP 请求对象,通过 new 构造函数的形式
request.open('GET', requestURL);//使用 open() 函数打开一个新的请求
request.responseType = 'json';//设定 responseType 为 JSON,服务器将知道我们想要返回一个 JSON 对象,然后发送请求
request.send();
request.onload = function() {
var superHeroes = request.response;//保存了相应请求的数据 (访问 response 属性) 于变量 superHeroes ;这个变量现在含有 JSON
populateHeader(superHeroes);//将会用正确的数据填充<header>
showHeroes(superHeroes);//创建一个信息卡片,然后把它插入<section>中。
}
//定位 header
function populateHeader(jsonObj) {
var myH1 = document.createElement('h1');
myH1.textContent = jsonObj['squadName'];//参数为 jsonObj
header.appendChild(myH1);
var myPara = document.createElement('p');
myPara.textContent = 'Hometown: ' + jsonObj['homeTown'] + ' // Formed: ' + jsonObj['formed'];
header.appendChild(myPara);
}
function showHeroes(jsonObj) {
var heroes = jsonObj['members'];
for(i = 0; i < heroes.length; i++) {
var myArticle = document.createElement('article');
var myH2 = document.createElement('h2');
var myPara1 = document.createElement('p');
var myPara2 = document.createElement('p');
var myPara3 = document.createElement('p');
var myList = document.createElement('ul');
myH2.textContent = heroes[i].name;
myPara1.textContent = 'Secret identity: ' + heroes[i].secretIdentity;
myPara2.textContent = 'Age: ' + heroes[i].age;
myPara3.textContent = 'Superpowers:';
var superPowers = heroes[i].powers;
for(j = 0; j < superPowers.length; j++) {
var listItem = document.createElement('li');
listItem.textContent = superPowers[j];
myList.appendChild(listItem);
}
myArticle.appendChild(myH2);
myArticle.appendChild(myPara1);
myArticle.appendChild(myPara2);
myArticle.appendChild(myPara3);
myArticle.appendChild(myList);
section.appendChild(myArticle);
}
}
</script>
</body>
对象和文本间的转换
接收到一些字符串作为 JSON 数据,然后想要将它转换为对象。当想要发送 JSON 数据作为信息,将需要转换它为字符串,经常需要正确的转换数据
parse(): 以文本字符串形式接受 JSON 对象作为参数,并返回相应的对象。stringify(): 接收一个对象作为参数,返回一个对应的 JSON 字符串。
request.open('GET', requestURL);
request.responseType = 'text'; // now we're getting a string!
request.send();
request.onload = function() {
var superHeroesText = request.response; // get the string from the response
var superHeroes = JSON.parse(superHeroesText); // convert it to an object
populateHeader(superHeroes);
showHeroes(superHeroes);
}
var myJSON = { "name" : "Chris", "age" : "38" };
myJSON
var myString = JSON.stringify(myJSON);
myString