Javascript-对象

105 阅读10分钟

JavaScript 对象定义

在 JavaScript 中,对象是王。如果您理解了对象,就理解了 JavaScript。

在 JavaScript 中,几乎“所有事物”都是对象。

  • 布尔是对象(如果用 new 关键词定义)
  • 数字是对象(如果用 new 关键词定义)
  • 字符串是对象(如果用 new 关键词定义)
  • 日期永远都是对象
  • 算术永远都是对象
  • 正则表达式永远都是对象
  • 数组永远都是对象
  • 函数永远都是对象
  • 对象永远都是对象

所有 JavaScript 值,除了原始值,都是对象。

JavaScript 对象是易变的

对象是易变的:它们通过引用来寻址,而非值。

这点类似于OC中的浅拷贝。这个特性非常重要。

如果 person 是一个对象,下面的语句不会创建 person 的副本:

var x = person;  // 这不会创建 person 的副本。

对象 x 并非 person 的副本。它就是 person。x 和 person 是同一个对象。

对 x 的任何改变都将改变 person,因为 x 和 person 是相同的对象。

var person = {firstName:"Bill", lastName:"Gates", age:62, eyeColor:"blue"}
 
var x = person;
x.age = 10;           // 这将同时改变 both x.age 和 person.age

注释:JavaScript 变量不是易变的。只有 JavaScript 对象如此。

JavaScript 对象属性

JavaScript 属性

属性指的是与 JavaScript 对象相关的值。

JavaScript 对象是无序属性的集合。

属性通常可以被修改、添加和删除,但是某些属性是只读的。

访问 JavaScript 属性

objectName.property 

objectName["property"] 

objectName[expression]

JavaScript for...in 循环

JavaScript for...in 语句遍历对象的属性。

语法

for (variable in object) {
    要执行的代码
}

for...in 循环中的代码块会为每个属性执行一次。

循环对象的属性:

实例

var person = {fname:"Bill", lname:"Gates", age:62}; s
//x 得到的是属性名称 
for (x in person) {
    txt += person[x];
}

添加新属性

person.nationality = "English";

删除属性

var person = {firstName:"Bill", lastName:"Gates", age:62, eyeColor:"blue"};
delete person.age;

delete 关键词会同时删除属性的值和属性本身。

删除完成后,属性在被添加回来之前是无法使用的。

delete 操作符被设计用于对象属性。它对变量或函数没有影响。

delete 操作符不应被用于预定义的 JavaScript 对象属性。这样做会使应用程序崩溃。

原型属性

这个有待实践

JavaScript 对象继承了它们的原型的属性。

delete 关键词不会删除被继承的属性,但是如果您删除了某个原型属性,则将影响到所有从原型继承的对象。

JavaScript 对象方法

var person = {
  firstName: "Bill",
  lastName : "Gates",
  id       : 648,
  fullName : function() {
    return this.firstName + " " + this.lastName;
  }
};

JavaScript 方法

JavaScript 方法是能够在对象上执行的动作。

JavaScript 方法是包含函数定义的属性。

属性
firstNameBill
lastNameGates
age62
eyeColorblue
fullNamefunction() {return this.firstName + " " + this.lastName;}

方法是存储为对象属性的函数。

this 关键词

在 JavaScript 中,被称为 this 的事物,指的是拥有该 JavaScript 代码的对象。

this 的值,在函数中使用时,是“拥有”该函数的对象。

请注意 this 并非变量。它是关键词。您无法改变 this 的值。

访问对象方法

请使用如下语法创建对象方法:

methodName : function() { 代码行 }

请通过如下语法来访问对象方法:

objectName.methodName()

使用内建方法

此例使用 String 对象的 toUpperCase() 方法,把文本转换为大写:

var message = "Hello world!";
var x = message.toUpperCase();

x 的值,在以上代码执行后将是:

HELLO WORLD!

添加新的方法

向对象添加方法是在构造器函数内部完成的:

实例

function person(firstName, lastName, age, eyeColor) {
    this.firstName = firstName;  
    this.lastName = lastName;
    this.age = age;
    this.eyeColor = eyeColor;
    this.changeName = function (name) {
        this.lastName = name;
    };
}

changeName() 函数 name 的值赋给了 person 的 lastName 属性。

现在您可以尝试:

myMother.changeName("Jobs");

通过用 myMother “替代” this,JavaScript 清楚您指的是哪个 person。

JavaScript 显示对象

显示对象属性

对象的属性可显示为字符串:

const person = {
  name: "Bill",
  age: 19,
  city: "Seattle"
};

document.getElementById("demo").innerHTML =
person.name + "," + person.age + "," + person.city;

在循环中显示对象

可以在循环中收集对象的属性:

const person = {
  name: "Bill",
  age: 19,
  city: "Seattle"
};

let txt = "";
for (let x in person) {
txt += person[x] + " ";
};

document.getElementById("demo").innerHTML = txt;

您必须在循环中使用 person[x]。

person.x 将不起作用(因为 x 是一个变量)。

使用 Object.values()

通过使用 Object.values(),任何 JavaScript 对象都可以被转换为数组:

const person = {
  name: "Bill",
  age: 19,
  city: "Seattle"
};

const myArray = Object.values(person);

myArray 现在是 JavaScript 数组,可以显示了:

自 2016 年以来,所有主要浏览器都支持 Object.values()

ChromeIEFirefoxSafariOpera
54 (2016)14 (2016)47 (2016)10 (2016)41 (2016)

使用 JSON.stringify()

任何 JavaScript 对象都可以使用 JavaScript 函数 JSON.stringify() 进行字符串化(转换为字符串):

const person = {
  name: "Bill",
  age: 19,
  city: "Seattle"
};

let myString = JSON.stringify(person);

日期字符串化

JSON.stringify 将日期转换为字符串:

const person = {
  name: "Bill",
  today: new Date()
};

let myString = JSON.stringify(person);
//{"name":"Bill","today":"2022-09-16T07:32:51.949Z"}
document.getElementById("demo").innerHTML = myString;

函数字符串化

JSON.stringify 不会对函数进行字符串化:

如果在字符串化之前将函数转换为字符串:

const personThree = {
    name: "Bill",
    today: new Date(),
    age: function () {return 19;}
};
personThree.age = personThree.age.toString();
let myString = JSON.stringify(personThree);
//{"name":"Bill","today":"2022-09-16T07:35:04.174Z","age":"function () {return 19;}"}
document.getElementById("demo").innerHTML = myString;

数组字符串化

也可以对 JavaScript 数组进行字符串化:

实例

const arr = ["Bill", "Steve", "Elon", "David"];

let myString = JSON.stringify(arr);
document.getElementById("demo").innerHTML = myString;

JavaScript 对象访问器

JavaScript 访问器(Getter 和 Setter)

ECMAScript 5 (2009) 引入了 Getter 和 Setter。

Getter 和 Setter 允许您定义对象访问器(被计算的属性)。


JavaScript Getter(get 关键词)

本例使用 lang 属性来获取 language 属性的值。

// 创建对象:
var person = {
  firstName: "Bill",
  lastName : "Gates",
  language : "en",
  get lang() {
    return this.language;
  }
};

// 使用 getter 来显示来自对象的数据:
document.getElementById("demo").innerHTML = person.lang;

JavaScript Setter(set 关键词)

本例使用 lang 属性来设置 language 属性的值。

实例

var person = {
  firstName: "Bill",
  lastName : "Gates",
  language : "",
  set lang(lang) {
    this.language = lang;
  }
};

// 使用 setter 来设置对象属性:
person.lang = "en";

// 显示来自对象的数据:
document.getElementById("demo").innerHTML = person.language;

JavaScript 函数还是 Getter?

下面两个例子的区别在哪里?

例子 1

var person = {
  firstName: "Bill",
  lastName : "Gates",
  fullName : function() {
    return this.firstName + " " + this.lastName;
  }
};

// 使用方法来显示来自对象的数据:
document.getElementById("demo").innerHTML = person.fullName();

例子 2

var person = {
  firstName: "Bill",
  lastName : "Gates",
  get fullName() {
    return this.firstName + " " + this.lastName;
  }
};

// 使用 getter 来显示来自对象的数据:
document.getElementById("demo").innerHTML = person.fullName;

例子 1 以函数形式访问 fullName:person.fullName()。

例子 2 以属性形式访问 fullName:person.fullName。

第二个例子提供了更简洁的语法。

Object.defineProperty() 方法也可用于添加 Getter 和 Setter:


// 定义对象
var obj = {counter : 0};

// 定义 setters
Object.defineProperty(obj, "reset", {
  get : function () {this.counter = 0;}
});
Object.defineProperty(obj, "increment", {
  get : function () {this.counter++;}
});
Object.defineProperty(obj, "decrement", {
  get : function () {this.counter--;}
});
Object.defineProperty(obj, "add", {
  set : function (value) {this.counter += value;}
});
Object.defineProperty(obj, "subtract", {
  set : function (value) {this.counter -= value;}
});

// 操作计数器:
obj.reset;
obj.add = 5;
obj.subtract = 1;
obj.increment;
obj.decrement;

浏览器支持

Internet Explorer 8 或更早的版本不支持 Getter 和 Setter:

Yes9.0YesYesYes

JavaScript 对象构造器

实例

function Person(first, last, age, eye) {
    this.firstName = first;
    this.lastName = last;
    this.age = age;
    this.eyeColor = eye;
}

为对象添加属性

var myFather = new Person("Bill", "Gates", 62, "blue");
var myMother = new Person("Steve", "Jobs", 56, "green");
//新属性被添加到 myFather。不是 myMother,也不是任何其他 person 对象。
myFather.nationality = "English";

为对象添加方法

myFather.name = function () {
    return this.firstName + " " + this.lastName;
};

新方法被添加到 myFather。不是 myMother,也不是任何其他 person 对象。

为构造器添加属性

与向已有对象添加新属性不同,您无法为对象构造器添加新属性:

实例

Person.nationality = "English";

如需向构造器添加一个新属性,您必须添加到构造器函数:

实例

function Person(first, last, age, eyecolor) {
    this.firstName = first;
    this.lastName = last;
    this.age = age;
    this.eyeColor = eyecolor;
    this.nationality = "English";
}

JavaScript 对象原型

原型继承

所有 JavaScript 对象都从原型继承属性和方法。

日期对象继承自 Date.prototype。数组对象继承自 Array.prototype。Person 对象继承自 Person.prototype。

Object.prototype 位于原型继承链的顶端:

日期对象、数组对象和 Person 对象都继承自 Object.prototype。

使用 prototype 属性

JavaScript prototype 属性允许您为对象构造器添加新属性:

function Person(first, last, age, eyecolor) {
    this.firstName = first;
    this.lastName = last;
    this.age = age;
    this.eyeColor = eyecolor;
}
Person.prototype.nationality = "English";

JavaScript prototype 属性也允许您为对象构造器添加新方法:

function Person(first, last, age, eyecolor) {
    this.firstName = first;
    this.lastName = last;
    this.age = age;
    this.eyeColor = eyecolor;
}
Person.prototype.name = function() {
    return this.firstName + " " + this.lastName;
};

JavaScript ES5 对象方法

ECMAScript 5 (2009) 向 JavaScript 添加了许多新的对象方法。

管理对象

// 以现有对象为原型创建对象
Object.create()

// 添加或更改对象属性
Object.defineProperty(object, property, descriptor)

// 添加或更改对象属性
Object.defineProperties(object, descriptors)

// 访问属性
Object.getOwnPropertyDescriptor(object, property)

// 以数组返回所有属性
Object.getOwnPropertyNames(object)

// 访问原型
Object.getPrototypeOf(object)

// 以数组返回可枚举属性
Object.keys(object)

保护对象

// 防止向对象添加属性
Object.preventExtensions(object)

// 如果属性可以添加到对象,则返回 true
Object.isExtensible(object)

// 防止更改对象属性(不是值)
Object.seal(object)

// 如果对象被密封,则返回 true
Object.isSealed(object)

// 防止对对象进行任何更改
Object.freeze(object)

// 如果对象被冻结,则返回 true
Object.isFrozen(object)

更改属性值

语法

Object.defineProperty(object, property, {value : value})

实例

此例更改属性值:

const person = {
  firstName: "Bill",
  lastName : "Gates",
  language : "EN"
};

// 修改属性
Object.defineProperty(person, "language", {value : "NO"});

更改元数据

ES5 允许更改以下属性元数据:

writable : true      // 属性值可更改
enumerable : true    // 属性可枚举
configurable : true  // 属性可重新配置
writable : false     // 属性值不可更改
enumerable : false   // 属性不可枚举
configurable : false // 属性不可重新配置

ES5 允许更改 getter 和 setter:

// 定义 getter
get: function() { return language }
// 定义 setter
set: function(value) { language = value }

此例设置 language 为只读:

Object.defineProperty(person, "language", {writable:false});

这个例子使 language 不可枚举:

Object.defineProperty(person, "language", {enumerable:false});

列出所有属性

这个例子列出了一个对象的所有属性:

实例

const person = {
  firstName: "Bill",
  lastName : "Gates",
  language : "EN"
};

Object.defineProperty(person, "language", {enumerable:false});
Object.getOwnPropertyNames(person);  // 返回数组的数组

添加属性

此例向对象添加新属性:const声明的对象也可以添加哦

实例

// 创建对象
const person = {
  firstName: "Bill",
  lastName : "Gates",
  language : "EN"
};

// 添加属性
Object.defineProperty(person, "year", {value:"2008"});

添加 Getter 和 Setter

Object.defineProperty() 方法也可以用来添加 Getter 和 Setter:

// 创建对象
const person = {firstName:"Bill", lastName:"Gates"};

// 定义 getter
Object.defineProperty(person, "fullName", {
  get: function () {return this.firstName + " " + this.lastName;}
});

JavaScript Map 对象


Map 对象存有键值对,其中的键可以是任何数据类型。

Map 对象记得键的原始插入顺序。

Map 对象具有表示映射大小的属性。


基本的 Map() 方法

MethodDescription
new Map()创建新的 Map 对象。
set()为 Map 对象中的键设置值。
get()获取 Map 对象中键的值。
entries()返回 Map 对象中键/值对的数组。
keys()返回 Map 对象中键的数组。
values()返回 Map 对象中值的数组。

Map() 属性

PropertyDescription
size获取 Map 对象中某键的值。

创建 Map 对象

能够使用对象作为键是 Map 的一个重要特性。

// 创建对象
const apples = {name: 'Apples'};
const bananas = {name: 'Bananas'};
const oranges = {name: 'Oranges'};

// 创建新的 Map
const fruits = new Map();

// Add new Elements to the Map
fruits.set(apples, 500);
fruits.set(bananas, 300);
fruits.set(oranges, 200);

您可以将 Array 传递给 new Map() 构造函数:

// 返回
const apples = {name: 'Apples'};
const bananas = {name: 'Bananas'};
const oranges = {name: 'Oranges'};

// 创建新的 Map
const fruits = new Map([
[apples, 500],
    [bananas, 300],
    [oranges, 200]
]);

获取键的值

get() 方法获取 Map 中键的值:

实例

fruits.get(apples);    // 返回 500

get里面需要是apples对象

其他 Map() 方法

方法描述
clear()删除 Map 中的所有元素。
delete()删除由键指定的元素。
has()如果键存在,则返回 true。
forEach()为每个键/值对调用回调。

JavaScript 对象 vs Map

JavaScript 对象和 Map 之间的差异:

对象Map
Size对象没有 size 属性Maps 有 size 属性
键类型对象键必须是字符串(或符号)Map 键可以是任何数据类型
键顺序对象键没有很好地排序Map 键按插入排序
默认对象有默认键Map 没有默认键

JavaScript Set 对象


Set 是唯一值的集合。

每个值在 Set 中只能出现一次。

一个 Set 可以容纳任何数据类型的任何值

好像每个语言的Set都是这种特性


如何创建 Set

创建一个 Set 并添加现有变量:

// 创建 Set
const letters = new Set();

// 向 Set 添加一些值
letters.add("a");
letters.add("b");
letters.add("c");

将 Array 传递给 new Set() 构造函数:

// 创建新的 Set
const letters = new Set(["a","b","c"]);

对于 Set,typeof 返回对象:

typeof letters;      // 返回 object。

对于 Set,instanceof Set 返回 true:

letters instanceof Set;  // 返回 true

Set 对象的方法和属性

new Set()创建新的 Set 对象。
add()向 Set 添加新元素。
clear()从 Set 中删除所有元素。
delete()删除由其值指定的元素。
entries()返回 Set 对象中值的数组。
has()如果值存在则返回 true。
forEach()为每个元素调用回调。
keys()返回 Set 对象中值的数组。
values()与 keys() 相同。
size返回元素计数。