前言
- 学习面向对象时我们常说“万物皆对象”,当然在JavaScript中也不例外。不夸张地说:没有理解对象,就无法理解JavaScript。本文将向你展现对象的详细内容,希望对你有帮助。
1. 对象的定义
1.1 “万物皆对象”一探究竟
1.1.1 都是对象
-
布尔类型通过new Boolean()创建时是对象
-
数字类型通过new Number()创建时是对象
-
字符串类型通过new String()创建时是对象
-
Date、Math、Array、RegExp本身就是对象
-
函数用typeof检测返回的是“function”,但其有属性和方法,也像是对象(函数通过new Function()创建时是对象)
-
Object是对象的对象
1.1.2 也有例外
-
原始数据类型有 number、boolean、string、null、undefined
-
其中null也是对象类型
typeof true //boolean
typeof 123 //number
typeof "str" //string
typeof undefined //undefined
typeof null //object
复制代码
1.1.3 结论:
-
原始数据类型的number、boolean、string、undefined不是对象类型
-
function关键字创建的函数不是对象类型
-
其余都是对象类型
1.2 到底什么是对象?
- 首先看看下面的对象定义
var Person = {
name: "一灯",
age: 23,
task: function() {
console.log('写代码!')
}
}
复制代码
- 是不是很像变量的定义呢?
var name = "一灯"
复制代码
-
实际上,对象就是一个变量,变量即是一个容器,只不过对象这个容器可以装各种类型的数据,而普通变量只能装某种类型的数据。
-
可以把对象理解为一个超级变量。
1.3 对象的属性和方法
-
刚说到对象是一个容器,里面装的就是属性和方法
-
方法:即对象里面定义的函数,如上面的task函数
-
属性:除了方法,其余的都是属性,如上面的name属性
1.4 创建对象的方式(这里不作详细讨论)
-
通过字面量创建(最简单的),即上面的那种
-
通过new Object()
var Person = new Object()
Person.name = "一灯"
Person.age = 23
Person.task = function() {
console.log('写代码!')
}
复制代码
-
通过构造函数
-
通过Object.create()
1.5 对象的赋值
- 先看看普通变量的赋值
var a = 10
var b = a
var b = 20
console.log(a) //a = 10,b的改变不会影响a
复制代码
- 对象赋值会怎样呢?
var Person = {
name: "一灯",
age: 23,
}
var a = Person
a.age = 24
console.log(Person.age) //Person.age = 24,受到了a的影响
复制代码
- 结论:对象的“赋值”不是赋值,而赋的是地址,两个对象指向了同一个地址,因此会相互影响。
2. 属性
2.1 属性的访问方式
- objectName.property
- objectName["property"] (注意加引号)
- objectName[表达式] (表达式的结果必须是一个属性名,本质和第2种是一样的)
//1
Person.age
//2
objectName["age"]
//3
var a = "age"
objectName[a]
复制代码
2.2 for...in遍历属性
var Person = {
name: "一灯",
age: 23,
tel: 123456
}
var str = ''
for (x in Person) {
str += Person[x]+" ";
}
console.log(str) //一灯 23 123456
复制代码
2.3 添加属性
- 可以给一个已定义的对象添加属性
var Person = {
name: "一灯",
age: 23
}
Person.tel = 123456
console.log(Person) //{ name: '一灯', age: 23, tel: 123456 }
复制代码
- 若属性已经存在,则会修改属性
var Person = {
name: "一灯",
age: 23
}
Person.age = 24
console.log(Person) //{ name: '一灯', age: 24 }
复制代码
2.4 删除属性
- 可通过delete关键字删除属性
var Person = {
name: "一灯",
age: 23
}
delete Person.age
console.log(Person) //{ name: '一灯' }
复制代码
- 使用delete需要知道的几点:
- 属性值和属性本身都会被删除,删除后不可再使用,除非再次添加该属性
- delete仅用于删除对象属性,对其他无效
- 切记不要删除对象中不存在的属性,以免程序崩溃
- delete不会删除继承的属性
2.5 属性的属性
- 是的,你没有看错,对象的属性也是有属性的,属性值只是其中一个属性
- 对象属性还有其他三个属性:可枚举、可配置、可读写,后面会介绍如何操作这些属性
3. 方法
3.1 this关键字(注意:这里是指对象方法中的this,关于this单独讲)
- 指的是方法的所有者,即该方法隶属的对象(下面例子中this隶属于person对象)
var person = {
name: "一灯",
age: 23,
show: function() {
console.log("Hello" + this.name)
}
}
person.show() //Hello一灯
复制代码
3.2 方法的访问
- 方法通过 objectName.methodName() 的形式访问,如上面的例子:person.show()
3.3 添加方法
person.info = function () {
return this.name + "-" + this.age
}
复制代码
4. 访问器
- 可通过 getter 和 setter 操作对象访问器
4.1 getter(使用get关键字)
var person = {
name: "一灯",
age : 23,
get getName() {
return this.name;
}
}
console.log(person.getName) //一灯
复制代码
4.2 setter(使用set关键字)
var person = {
name: "一灯",
age : 23,
set setName(name) {
this.name = name;
}
}
person.setName = "111"
console.log(person.name) //111
复制代码
4.3 函数 VS 访问器
- 你已经发现了,这种方式似乎和函数很像
//函数实现getter
var person = {
name: "一灯",
age : 23,
getName: function() {
return this.name;
}
}
//getter:console.log(person.getName),语法更简洁
console.log(person.getName()) //一灯
//函数实现setter
var person = {
name: "一灯",
age : 23,
setName: function(name) {
this.name = name;
}
}
//setter:person.setName = "111",语法和操作属性一样
person.setName(111)
console.log(person.name) //111
复制代码
-
对比发现: 访问器属性语法更简洁,并且方法和属性的操作一致
-
值得注意的一点:访问器属性对错误不那么敏感
//setter
var person = {
name: "一灯",
age : 23,
set setName(name) {
this.name = name;
}
}
person.sdetName = "111" //setName拼错,但是没有报错
console.log(person.name)
//函数
var person = {
name: "一灯",
age : 23,
setName: function(name) {
this.name = name;
}
}
person.sdetName(111) //setName拼错,报错了
console.log(person.name)
复制代码
4.4 Object.defineProperty()
- 添加访问器属性的另一种方式,通过Object.defineProperty(),格式如下:
var person = {
name: "一灯",
age: 23
}
//getter
Object.defineProperty(person, "getName", {
get: function() {
return this.name
}
})
console.log(person.getName) //一灯
//setter
Object.defineProperty(person, "setName", {
set: function(name) {
return this.name = name
}
})
person.setName = 111
console.log(person.name) //111
复制代码
5. 构造函数
-
JavaScript采用构造的函数创建对象是一种常见的方法,通常采用首字母大写的驼峰法命名对象
-
然后通过new关键字创建对象实例
function Person(name, age) {
this.name = "一灯",
this.age = 23,
this.show = function() {
console.log(this.name + '-' +this.age)
}
}
var person = new Person('一灯', 23)
person.show() //一灯-23
复制代码
5.1 this关键字
- this关键字隶属于通过构造函数创建的实例,上面的例子this指向person对象
5.2 添加属性和方法到对象
//添加属性
person.tel = 123456
//添加方法
person.task = function() {
console.log("写代码!")
}
复制代码
5.3 添加属性和方法到构造函数
- 向构造函数添加属性和方法与对象中不同,像这样Person.tel = 123456 是无效的
- 只能在构造函数中添加
function Person(name, age) {
this.name = "一灯",
this.age = 23,
this.tel = 123456, //新增的属性
this.show = function() {
console.log(this.name + '-' +this.age)
},
this.task = function() { //添加的方法
console.log("写代码!")
}
}
复制代码
5.4 内置的构造函数
- 即我们熟悉的Object、Function、Array、Date、RegExp、String、Boolean、Number
- 注意:Math()是一个全局对象,不能使用new
- **特别注意:**虽然有原始数据类型(boolean、number等等)的对象版本,但尽量避免使用new 的方式创建,使用原始值会更快。
6. 原型prototype
-
js中所有对象都从原型中继承属性和方法,原型是非常重用的概念
-
上一章节说到,向构造函数中添加属性或方法需要在构造函数中添加。还有一种方式是:通过原型
function Person(name, age) {
this.name = "一灯",
this.age = 23,
this.show = function() {
console.log(this.name + '-' +this.age)
}
}
Person.prototype.tel = 123456
Person.prototype.task = function() {
console.log("写代码!")
}
var person = new Person()
console.log(person.tel) //123456
person.task() //写代码!
复制代码
- 关于原型/原型链的详细内容戳这里