对象的创建

外部属性定义方式

/*
    在js中并不存在类,所以可以直接通过object来创建对象
    但是使用如下方式创建,带来最大的问题是,由于没有类的约束
    无法实现对象的重复利用,并且没有一个约定,在操作时会带来问题
*/
var person = new Object();
person.name = 'leo';
person.age = 33;
person.say = function(){
    alert(this.name + ',' + this.age);
}


使用json格式定义
/*
json的意思就是javascript simple object notation
json就是js的对象,但是它省去了xml中标签,而是通过{}来完成对象的说明
*/
var person = {
    name :'张三',
    age :23,
    say:function(){
        alert(this.name + ',' + this.age);
    }//最后一个属性之后不能有,
}

person.say();

/*
    通过json依然可以创建对象数组,创建的方式和js的数组一样
*/

var ps =[
    {name : 'leo',age:22},
    {name : 'le',age :30}
];

/*
    创建一个组用户,用户的属性有
    name :string,age:int,friends:array
    List<person> ps = new ArrayList<person>();
    ps.add(new Person('leo',22,['ada','alice']));
*/


ps = [
    {
        name :'leo',
        age :22,
        friendes :['Ada','Alice']
    },
    {
        name : 'le',
        age :30,
        friends:['Ada','chris']
    }
]


工厂方式

/*
    通过工厂的方式来创建person对象
    在createPerson中创建一个对象
    然后为这个对象设置相应的属性和方法之后返回这个对象
*/

function createPerson(name,age){
    var o = new Object();
    o.name = name;
    o.age =age;
    o.say = functon (){
        alert(this.name+','+this.age);
    }
    return o;
}

/*
 使用工厂的方式,虽然有效的解决了类的问题,但是依然存在另外个问题
 我们无法检测对象p1和p2的数据类型
*/

var p1 = createPerson('leo',22);
var p2 = createPerson('ada',30);
// 没有办检测p1和ps的数据类型通过typeof仅仅只能检测出object类型,如果希望使用instanceof来检测的话,无法确定检测类型
p1.say();
p2.say();



构造函数方式

//通过new person来创建对象
var p1 = new person('leo',22);
var p2 = new person('le',30)

p1.say();
p2.say();

/*
    使用构造函数的方式可以通过以下方式来检测
    对象的类型
*/
console.log(p1 instanceof Person);

/*
    使用构造函数创建所带来的第一个问题就是每个对象中
    都会存在一个方法的拷贝,如果对象的行为很多的话空间
    的占用率就会大大增加
    可以将函数放在全局变量中定义,这个可以让类中的行为指向同一个函数
*/

console.log(p1.say == p2.say);
如果在person内部来创建方法,这两个不是一样的

使用如下方式可以解决空间利用的问题
this.say = say;


/*
    将行为设置为全局的行为,如果将所有的方法都设计为全局函数的时候
    这个函数就可以被winodw调用,此时就破坏对蠏的封装性
    而且如果某个对象有大量的方法,就会导致整个代码中充斥着大量的全局函数
    这样将不利于开发
*/


function say(){
    console.log(this.name+','+this.age);
}


基于原型的方式

/*
 基于原型的创建虽然可以有效的完成封装,但是依然有一些问题
 1、无法通过构造函数来设置属性值
 2、当属性中有引用类型变量是,可能存在变量值重复
*/

function person(){

}

person.prototype = {
    constructor :person,
    name : 'leo',
    age :30,
    friends:['le','chris'],
    say:function(){
        console.log(this.name +'['+ this.friends+']');
    }
}

var p1 = new person();
p1.name = 'john';
p1.say(); //john[le,chris]
//会在原型中找friends,所以mike是在原型中增加的
p1.friends.push('ni'); //为p1增加了一个朋友
var p2 = new Person();
//此时原型中就多了一个Mike,这就是原型所带来的第二个问题
p2.say();


基于构造函数和原型方式
/*
为了解决原型所带来的问题,此外需要通过组合构造函数和原型来实现对象的创建
将属性在构造函数中定义,将方法在原型中定义
这种有效集合了两者的优点,是目前最为常用的一种方式
*/

function person(name,age,friends){
    //属性在构造函数中定义
    this.name = name;
    this.age = age;
    this.friends = friends;
}

person.prototype = {
    constructor = person;
    //方法在原型中定义
    say : function(){
        console.log(this.name +"["+this.friends+"]")
    }
}

//此时所以的属性都是保存在自己的空间中的
var p1 = new Person('leo',23,['Ada','chris']);
p1.name = 'john';
p1.friends.push('Mike'); //为p1增加了一个朋友
p1.say();
var p2 = new Person('Ada',33,['leo']);
//此时原型中就多了一个mike,这就是原型所带来的第二个问题
p2.sav();


动态原型的方式
为了让定义的方式更加符合java的需求,就把定义方法的原型代码放置到person这个构造函数中

function Person(name,age,friends){
    this.name = name;
    this.age = age;
    this.friends = friends;
    //不能使用重写的方式定义
    /*
        person.prototype = {
            constructor:person,
            say:function(){
                console.log(this.name + "["+this.friends+"]");
            }
        }
    */
    /*
    判断person.prototype.asy是否存在,如果不存在就表示需要创建
    当存在之后就不会在创建
    */
    if(!person.prototype.say){
        person.prototype.say = function(){
            console.log(this.name +"['+this.friends+']")
        }
    }
}
原文地址:https://www.cnblogs.com/leole/p/4165660.html