JavaScript中的创建对象方式

时间:2022-08-30 10:37:36


-----看了好多的资料,整理一下,加上自己的理解,希望看见的人有什么问题,请多多指教!

对象定义:无序属性的集合,其属性可以包含基本值、对象、函数。严格来讲,对象是一组没有特定顺序的值,也可以理解为散列表,无非就是一组名值对,其中值可以是数据或函数。

首先,用对象字面量的方法创建对象:
var person = {
name: "Lee",
sayName: function(){
alert(this.name);
}
}
这种方式创建很多对象,会产生大量的重复代码,工厂方式解决该问题。
工厂方式用函数来封装特定接口创建对象
function fnc(name,age){
var f = new Object();
f.name = name;
f.age = age;
f.show = function(){
alert(this.name);
}
return f;
}
var f1 = fnc("Lee",22);
var f2 = fnc("Zhao",22);
优势:可以无数次调用这个函数,每次都会返回一个对象
劣势:无法确定一个对象的类型
构造函数模式可以创建自定义的构造函数,定义对象类型的属性和方法
function fnc(name,age){
this.name = name;
this.age = age;
this.show = function(0{
alert(this.name);
})
}
var f1 = new fnc("Lee",22);
var f2 = new fnc("Zhao",22);
这种模式与工厂模式的区别:
1.没有显示的创建对象2.直接将属性和方法赋值给了this对象3.没有return劣势:每个方法都要在每个实例上差创建一遍,没有共享,没有封装性可言。
原型模式每个函数都有一个prototype(原型)属性,这个属性是一个指针,指向一个对象,而对象包含可以由特定类型的所有实例共享的属性和方法。不必在构造函数中,定义对象实例的一些方法或者属性,而是直接将这些添加到原型对象中。
function fnc(){}
fnc.prototype.name = "Lee";
fnc.prototype.age = 22;
fnc.prototype.show = function(){
alert(this.name);
}

var f1 = new fnc();
f1.show(); //Lee
var f2 = new fnc();
f2.show(); //Lee
图解原型,构造函数,实例的关系:
JavaScript中的创建对象方式



       fnc是一个构造函数,里面有一个属性,叫做Prototype,指向构造函数性的原型,原型里有一个constructor属性,又指向回该构造函数,f1,f2为两个实例,他们底下有一个_proto_([[Prototype]])属性,指向了原型,也就说明了f1和f2与构造函数没有什么直接的关系。
       对于一个实例上的属性,首先,从对象实例开始搜索,如果在实例中找到了具有该属性的名字,就返回该值,如果没有找到,就继续搜索原型对象,在原型对象中查找,直至找到,否则,返回undefined。
       当然我们在实例上添加一个属性的话,该属性名如果和原型上的属性名重复,这样子, 该属性会覆盖原型上的属性,但是不会修改原型上的属性,可是使用delete实例属性,又可以恢复原形的属性。

function fnc(){}
fnc.prototype.name = "Lee";
fnc.prototype.age = 22;
fnc.prototype.show = function(){
alert(this.name);
}

var f1 = new fnc();
var f2 = new fnc();
f1.name = "Zhao";

alert(f1.name); //Zhao
alert(f2.name); //Lee

delete f1.name;
alert(f1.name); //Lee

可以使用hasOwnProperty()方法可以判断一个属性在事例中,还是在原型中,这个方法是继承Object的,只有给定属性在实例中,才会返回true。操作符in,无论该属性存在实例还是原型,都返回true。可以用该方法判断一个属性存在哪里:
function juge(object,name){
return!object.hasOwnPropertype(name)&&(name in object)
}

接下来再看一段代码:
function fnc(){}
fnc.prototype = {
constructor: fnc,
name: "Lee",
friends: ["Zhao","Sonly"],
}

var f1 = new fnc();
var f2 = new fnc();
f1.friends.push("Day");

alert(f1.friends); //Zhao,Sonly,Day
alert(f2.friends); //Zhao,Sonly,Day

传递引用类型的值,问题很明显,在一个实例进行了修改,另一个也就一样修改了,这就是应为在原型上进行了修改,因此,问题就是共享的同样的可能

构建函数+原型模式
构造函数用于实现实力属性,原型模式用于定义方法和共享的属性。
这样子的模式组合,在构造函数定义的属性,修改时,只会影响修改的对象,其他的不受影响。
function Fnc(name,age){
this.name = name;
this.age = age;
this.friends = ["Sonly","Chat"];
}
Fnc.prototype = {
constructor: Fnc,
show: function(){
alert(this.name);
}
}
var f1 = new Fnc("Lee",22);
var f2 = new Fnc("Tuyg",22);
f1.friends.push("Haye");

alert(f1.friends); //Sonly,Chat,Haye
alert(f1.friends); //Sonly,Chat

这种模式,是流传最广的,也是能实现共享,同时又互不影响的一种完美结合的方法。
当然还有其他的一些创建对象的方法,但是这四种,是最基础的,最后一种相结合的方式是最直接完美的,各有各的优点,同时也有缺点,根据喜好,自创对象。