面向对象都有类的概念,通过类可以创建任意多个具有相同属性和方法的对象。
每个对象都是基于一个引用类型创建的。
PS:阅读JS高级程序教程第六章笔记
1、对象
创建:new Object() / 对象字面量
var person = new Object();
person.name = "qwe"
person.sayName = function() { ... }
-----------------------------------------------------------------------
var person = {
name: 'qwe',
sayName: function() {... }
}
ES5定义只有内部使用的特性(attribute)时,描述了属性(property)特征。规范是将其放在[[ ]]中。属性分为以下两种:
1)数据属性
包含一个数据值,有4个描述其行为的特性:
[[Configurable]]、[[Enumerable]]、[[Writable]]、[[Value]]
前三个特性默认为true,[[Value]]会根据创建设置的值赋值。
Configurable设置为false后,不能再删除、修改对象的属性
var person = {}
Object.defineProperty(person, "name", {
configurable: false,
value: 'qwe'
})
console.log(person.name) // qwe
person.name = "asd"
console.log(person.name) // qwe
Enumerable表示能否通过for-in循环返回属性
2)访问器属性
[[Configurable]]、[[Enumerable]]、
[[get]]、[[set]]
var book = {
_year: 2004, // _表示只能通过对象方法访问的属性
edition: 1
}
// 定义对象数据属性year
Object.defineProperty(book, "year", {
// 获取属性值,返回_year属性
get: function() {
return this._year
},
// 设置year属性值,判断设置的值是否大于2004 再进行赋值操作
set: function(newValue) {
if(newValue > 2004){
this._year = newValue;
this.edition += newValue - 2004
}
}
})
book.year = 2006 // 赋值 set
console.log(book.year) // 2006 获取 get
PS:
修改属性的默认特性方法:Object.defineProperty()
读取:Object.getOwnPropertyDescriptor()
var propertyDes = Object.getOwnPropertyDescriptor(book, 'edition')
console.log(propertyDes.value)
2、创建对象
Object构造函数或者对象字面量可以实现创建单个对象,但是使用同一个接口创建很多对象,会产生大量的重复代码。
1)工厂模式
解决了创建多个相似对象的问题。
function createPerson(name){
var obj = new Object();
obj.name = name;
obj.getName = function(){
return this.name
};
return obj;
}
var person = createPerson('qwe')
console.log(person.getName())
问题:还是不知道一个对象的类型。
2)构造函数模式
ECMAScript中的构造函数可用来创建特定类型的对象。(Object和Array就属于原生的构造函数)
function Person(name){
this.name = name;
this.getName = function(){
return this.name
};
}
var person = new Person('qwe') // new操作符创建实例
console.log(person.getName())
与工厂方法不同:
- 没有显示的创建对象
- 直接将属性和方法赋给了this对象
- 没有return语句
- 命名以大写字母开头(为了区别于其他的函数)
- 使用new操作符创建实例
调用构造函数会经历四个步骤:
- 创建一个新对象
- 将构造函数的作用域赋给新对象(this指向该对象)
- 执行构造函数中的代码(为新对象添加属性)
- 返回新对象
person是Person的实例,Person是person的构造函数,因此person的构造函数属性constructor是指向Person的:
person.constructor == Person
// true
可以用来标识对象的类型,但是检测对象类型,基本上使用instanceof
:
person instanceof Person // true
person instanceof Object // true(所有对象都继承Object,函数是对象,函数对象)
PS:值类型用typeof判断,引用类型用instanceof判断
问题: 每创建一个实例,getName方法都会重新创建一遍,生成不同的Function实例,这是没必要的。
解决: 将函数抽取出来,放到构造函数外,设置成全局的函数
function Person(name){
this.name = name;
this.getName = getName
}
function getName(){
return this.name
}
但是,如果有很多的函数的话,就要定义很多的全局函数,这是不现实的。
这就引申出原型模式。