您的位置:首页 > Web前端 > JavaScript

JavaScript之对象(一)

2015-10-02 09:13 411 查看

JavaScript 自定义对象

模式主要有工厂模式,构造函数方式,原型模式, 组合模式,动态原型模式;
例子:

//工厂模式:对象识别问题,代码复用问题,无共享区域
function createPerson(name, age) {
var o = new Object();
o.name = name;
o.age = age;
o.sayName = function() {
alert(this.name);
};
return o;
}


//构造函数:代码复用问题,无共享区域
function Person(name, age) {
this.name = name;
this.age = age;
this.sayName = function() {
alert(this.name);
};
}


//原型模式: 对于函数来说可以,符合我们的要求,实现了共享;对于基本量来说,我们可以通过对实例新建一个同名的属性来得到实例变量;但是问题会出现引用类型,如果是引用类型的话,尽管也可以跟基本类型一样在实例 上新建一个同名的来覆盖,但在使用上就有些不合理(因为对象多半是有函数的),当我们直接在实例上调用了引用类型的方式时,其实是修改了原型中的对象。
function Person() {
}
//使用prototype属性逐一添加
var name = "Kin", age = 12;
Person.prototype.name = name;
Person.prototype.age = age;
Person.prototype.sayName = function() {
alert(this.name);
}
Person.prototype.friends = ["Mik", "Sell"];

//利用对象字面量重写prototype
Person.prototype = {
constructor : Person,
name : "Kin",
age : 12,
sayName : function() {
alert(this.name);
},
   friends : ["Mik", "Sell"]

};
//引用类型的问题在于,当我一个实例对象person1 调用了person1.friends.push("Jon")时,其实是修改原型中的friends,所以效果也就会出现在其他实例上了,当然我们可以直接复制(利用slice()来生成一个新的数组)并新建一个新的对象在person1上,也即person1.friends = person1.friends.slice(0, person1.friends.length).但这样往往比较麻烦,也容易忘记。


//组合模式(组合使用构造函数和原型,不足是看起来不像是一个对象的定义方式)
//定义实例变量
function Person(name, age) {
this.name = name;
this.age = age;
this.friends = ["shell", "dos"];
}
//定义类变量
Person.prototype = {
constructor : Person,
sayName : function() {
alert(this.name);
}
}


//动态原型模式
function Person(name, age) {
this.name = name;
this.age = age;
if(typeof this.sayName != "function") {
Person.prototype.sayName = function() {
alert(this.name);
};
//other also here
}
}


补充说明

在function 中定义的实例变量(也就是用this指定的)在没有用new 实例化之前在内存中是不存在的。

在函数创建之后(不用调用),该函数就会被创建一个prototype的属性(这个与在function中定义的不一样)。

在利用构造函数实例化一个“对象”后,该对象会有一个[[prototype]]内部属性,这个属性的值是构造函数的原型对象的引用(也是因为这个机制才可以实现“类机制”和“继承机制”),但是我们无法直接访问这个属性,但在主流浏览器都支持实例化对象有一个“__proto__”属性,该属性值等于[[prototype]].

在定义function后若是显示使用函数名去添加属性的话,此时的属性是已初始化的,也就是说在内存中分配了内存,但是这个内存区域的地址只有用函数名的引用才可以访问,而其实例对象是无法访问的;

在javascript中是没有类的定义的,其实现主要:this来设定作用域(模仿实例对象),prototype来实现继承的方式

在函数中定义的变量和函数如果是作为实例变量的,一定要用this.名称,否则会被解析器视为局部变量或是全局变量。

其实JS的构造函数对于实例化对象而言,就是一个方法,一个去为自己添加属性的方法,在这个方法中可能会运用到一些局部变量(没有用this.*=*(*代表变量),那么这些变量在函数出栈后,就会被销毁。

相关代码说明:

function Person() {
var test = "test"; //局部变量
this.here = "here"; //实例变量
this.sayAge = function() {
return "age";
};
}
console.log(Person.here); //undefined
console.log(Person.sayAge()); //Person.sayAge is not a function
//在外部定义
Person.sayAge2 = function() {
return "age";
}
Person.here2 = "outhere";
console.log(Person.here2); //outhere
console.log(Person.sayAge2()); //age
Person.prototype = {
constructor : Person,
name : "Kin",
age : 12,
friends : ["Sell", "Mik"],
sayName : function() {
return "name";
}
}
person1 = new Person();
person2 = new Person();
person1.sayAge2(); //person1.sayAge2 is not a function


相关图例:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: