简单来说:对象就是无序属性的集合,包含基本值、对象或者属性。
那么他的属性有哪些类型呢?
- 数据属性
- 访问器属性
访问器属性不包含数据值,包含一对getter和setter函数。
创建对象的方式有哪些?
工厂模式:
抽象了创建具体对象的过程
function creatPerson (name, age, job) {
var o = new Object();
o.name = name
o.age = age
o.job = job
o.sayName = function () {
console.log(this.name)
}
}
var person1 = new creatPerson('simoon', '27', 'job')
var person2 = new creatPerson('simoon2', '17', 'nojob')
它有一个问题就是:虽然解决了创建多个类似对象的问题,但却无法解决对象识别的问题。
构造函数模式:
function Person(name, age, job) {
this.name = name
this.age = age
this.job = job
this.sayName = function () {
console.log(this.name)
}
}
var person1 = new Person('simoon', '27', 'job')
var person2 = new Person('simoon2', '17', 'nojob')
与工厂函数的不同之处:
- 没有显示的创建对象
- 直接将属性和方法赋给了this
- 没有return语句
因为构造函数本身也是函数,所以一般给构造函数的首字母予以大写,以示区别。
要创建一个新实例,必须使用new操作符。
创建的实例,都有一个constructor的属性,指向构造函数。
person1.constructor == Person
//true
构造函数对比工厂模式的优势:
将来可以将构造函数的实例标识为一种特定的类型;
如果把构造函数当作正常的函数来用的话,他和普通的函数没有任何区别。它将所有的属性和方法挂载到window上,因为全局的this指向window。
Person('haimingyue', '12', 'student')
window.name
//"haimingyue"
构造函数的缺点:
每个方法都要在每个实例上面创建一次
因为es中的函数是对象,每定义一个函数就会实例化一个对象。
function Person(name, age, job) {
this.name = name
this.age = age
this.job = job
this.sayName = new Function("console.log(this.name)")
}
这样没实例化一个对象。就会创建一个sayname的方法,其实是没有必要的。
当然,也可以向下面这样写解决。但是这样写就没有封装的效果了。
function Person(name, age, job) {
this.name = name;
this.age = age;
this.job = job;
this.sayName = sayName;
}
function sayName () {
console.log(this.name)
}
原型模式
当我们创建一个函数的时候,es会自动为他添加一个prototype属性,它是一个指针,指向原型对象,原型对象上包含所有实例共享的属性和方法。
function person () {
}
person.prototype.name = "simoon";
person.prototype.age = "18";
person.prototype.job = "student";
person.prototype.sayName = function() {
console.log(this.name)
}
var person1 = new Person()
var person2 = new Person()
这种情况下,person1 和 person2 的属性和方法就是共享的了。
console.log(person1.sayName == person2.sayName)
// true
好了,下一章我们好好聊聊什么是原型对象。