创建方式:
字面量方式:
属性和方法都是静止的,不够灵活
var obj = {
name:"test",
sex:"male",
run:function(){
console.log("run");
}
}
使用object创建
属性和方法都是object的成员
var obj = new Object();
obj.name = "test";
obj.sex = "male";
obj.run = function(){
console.log("run");
}
使用工厂模式创建
将各个属性的值通过参数传递,根据模板快速产生对象。但对象的方法是一个函数对象,会导致每次调用工厂方法都会新创建一个函数对象,造成额外的成本开销。
function createObj(name,sex,run){
var test = new Object();
test.name = name;
test.sex = sex;
test.run = run;
return test;
}
var obj = createObj("test","male",new function(){console.log("run")});
使用构造函数创建
更像面向对象语言中的构造方法,利用this完成对象初始化。内存开销大。
function Obj(name,sex){
this.name = name;
this.sex = sex;
this.run = function(){
console.log("run");
}
}
var obj = new Obj("test","male");
原型创建
每一个构造函数都有一个prototype属性,指向另一个对象,这个对象的所有实例都会被构造函数的实例继承。也就是说,这个prototype属性相当于实例对象的父类,我们可以通过赋值给父类,子类再继承父类的方式来给实例对象赋值。这也意味着我们可以把那些不变的属性和方法,直接定义在prototype对象上。
function Obj(){}
Obj.prototype.name = "test";
Obj.prototype.sex = "male";
Obj.prototype.run = function(){
console.log("run");
}
var obj = new Obj();
console.log(obj);
构造函数+原型模式
不公用的属性或方法在构造函数中创建,避免属性共享,相同的属性和方法在原型模式中创建。
function Obj(name,sex){
this.name = name;
this.sex = sex;
}
Obj.prototype.major = "software";
Obj.prototype.run = function(){
console.log("run");
}
var obj = new Obj("test","male");
console.log(obj);
console.log(obj.major);
对象属性分为两种:数据属性和访问器属性。
数据属性:
每个属性名都对应一个属性描述对象,包含的是一个数据值的位置,在这可以对数据值进行读写。使用Object.getOwnPrototyDexcriptor()可以访问指定属性描述对象的4个特征值。若该对象的属性值不能直接访问,返回undefined。使用Object.defineProperty()可以修改指定属性描述对象的4个特征值。
function Obj(name,sex){
this.name = name;
this.sex = sex;
}
Obj.prototype.major = "software";
Obj.prototype.run = function(){
console.log("run");
}
var obj = new Obj("test","male");
console.log(Object.getOwnPropertyDescriptor(obj,"name"));
console.log(Object.getOwnPropertyDescriptor(obj,"major"));
Object.defineProperty(obj,"name",{value:"hhh"});
console.log(Object.getOwnPropertyDescriptor(obj,"name"));
value:该属性的数据值
writable:能否修改属性的值
enumerable:能否通过for-in循环返回属性
configurable:能否通过delete删除属性从而重新定义属性,能否修改属性的特性,或能否把属性修改为访问器属性,默认为true
访问器属性:
可以使用get和set取值和赋值,只能使用Object.defineProperty()定义。
function Obj(name,age){
this.name = name;
this._age = age;//内部属性
this.editor = 0;
}
Obj.prototype.major = "software";
Obj.prototype.run = function(){
console.log("run");
}
var obj = new Obj("test",18);
Object.defineProperty(obj,"age",{
get:function(){
return this._age;
},set:function(newAge){
if(newAge > 18){
this._age = 18;
this.editor++;
}
}
})
console.log(Object.getOwnPropertyDescriptor(obj,"age"));
console.log(obj.age);
obj.age = 20;
console.log(obj.age);
console.log(obj.editor);
this
在全局执行环境中,this指向的是全局对象,在浏览器中是window对象。当this出现在一个对象的方法中,其指向是该方法的拥有者。当this出现在构造函数中,则指向的是构造函数被调用时创建的对象。
this不是变量,不能改变它的值。
function Obj(name,sex){
this.name = name;
this.sex = sex;
this.desc = function(){
console.log(this.name);
}
}
var obj = new Obj("test","male");
obj.desc();
var obj2 = new Obj("hhh","male");
obj2.desc();
var obj = {
name:"test",
sex:"male",
desc:function(){
console.log(this.name);
}
}
obj.desc();
可以用call()和apply()更改this所指向的对象。
var obj = {
desc:function(age,sex){
console.log(this.name + "'s age is " + age);
}
}
var p1 = {
name:"test"
}
var p2 = {
name:"hhh"
}
obj.desc.call(p1,18,"male");
obj.desc.apply(p2,[20,"male"]);
也可以使用闭包函数实现私有属性的访问。
function Obj(name,sex){
var name = name;
var sex = sex;
this.getName = function(){
return name;
}
this.getSex = function(){
return sex;
}
}
var obj = new Obj("test","male");
console.log(name);
console.log(obj.getName());