JavaScript对象 -构建

首先,在js里,对象是由函数构建而成的。

创建对象的几种模式

1.工厂模式

function person(name,age,job) {
    var o=new Object();
    o.age=age;
    o.name=name;
    o.job=job;
    o.sayname=function () {
        console.log(this.name);
    }
    return o;
}

var person1=person("1",1,"1");
person1.sayname();
//检测对象什么类型
console.log(person1 instanceof Object);//true
console.log(person1 instanceof person);//FALSE

工厂模式解决了创建多个相似对象的问题,但是不知道如何知道一个对象的类型。

2.构造函数模式

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("1",1,"1");
person1.sayname();

console.log(person1 instanceof Object);//检测对象什么类型
console.log(person1 instanceof person);//都是true

  与工厂模式不同点:

1.没有显式创建对象

2.属性方法赋予给this对象

3.没有return语句

创建对象使用new时,调用构造函数会有一下几步

1.创建一个新对象

2.构造函数的作用域给新对象

3.执行构造函数的代码

3.返回新对象

任何函数,只要通过new来调用,那么他就可以作为构造函数,他的问题就是每个方法要在每个实例上重新构造一遍

上述sayname方法等同于下

this.sayname=new function("console.log(this.name)")

如果再新建对象person2

console.log(person1.sayname==person2.sayname) ;结果是FALSE

当然我们可以把这些函数放在外面,在构造函数内调用,但是这样就毫无封装性。3.

3.原型模式
每个函数都有一个prototype属性
function person() {
}
person.prototype.name="1";
person.prototype.age=12;
person.prototype.sayname=function () {
    console.log(this.name);
}

var person1=new person();
person1.sayname();       //1
var person2=new person();
person2.sayname();       //1

好处:让所有实例共享他的属性和方法

如果实例添加一个新属性且新属性与原型中的属性重名,那么就在实例中创建该属性,该属性会屏蔽掉原型中的该属性。

function person() {
}
person.prototype.name="1";
person.prototype.age=12;
person.prototype.sayname=function () {
    console.log(this.name);
}

var person1=new person();
person1.name="2";
person1.sayname();
delete person1.name;//删除新添加的属性
person1.sayname();  //会显示原型里的属性

接下来是重点:

function person() {
}
person.prototype={
    name:"1",
    age:12,
    sayname:function () {
        console.log(this.name);
    }
}
var friend=new person();
console.log(friend instanceof Object);  //true
console.log(friend instanceof person);   //true
console.log(friend.constructor == person);  //false
console.log(friend.constructor == Object);//true

person.prototype.sayhi=function () {
    console.log("hi");
}
friend.sayhi(); //hi

instanceof  判断一个变量是不是属于一个变量的实例。

constructor 属性返回对创建此对象的数组函数的引用。

friend是person的一个实例

所以向person中添加 Protype时friend也可以引用。

原型的动态性:

function person() {
}
var friend=new person();
console.log(friend instanceof Object);  //true
console.log(friend instanceof person);   //true
console.log(friend.constructor == person);  //true
console.log(friend.constructor == Object);  //true
console.log(friend.constructor);  //【Function:person】
person.prototype={
    constructor:person,
    name:"1",
    age:12,
    sayname:function () {
        console.log(this.name);
    }
}
friend.sayname();//报错

当执行到最后一句时会报错,原因是我们重写了整个原型对象。

大致就是这个样子,person原本指向person Protype,在重写原型对象后指向了new person Protype,但是friend仍然指向原来的person Protype,所以出现错误。

原型模式的问题:

function person() {
}
person.prototype={
    constructor:person,
    friends:["a","b","c"]
}
var person1=new person();
var person2=new person();
person1.friends.push("d");
console.log(person1.friends);//【a,b,c,d】
console.log(person2.friends);//[a,b,c,d]

会发现person2的friends也会有d

针对包含引用类型值的属性:

原因就是这个样子,person1引用Protype,所以修改person1就修改了person2。

最常用的创建对象对象

         --------------------组合使用构造函数模式和原型模式

因为构造函数模式new时会创建一个新对象,而原型模式就是用于定义方法和共享属性。

function person(name) {
    this.name=name;
    this.friends=['a']
}
person.prototype={
    constructor:person,
    sayname:function () {
        console.log(this.name);
    }
}
var person1=new person("1") ;
var person2=new person("2") ;
person1.friends.push("b");
console.log(person1.friends);
console.log(person2.friends);
console.log(person1.friends==person2.friends);
console.log(person1.sayname==person2.sayname);

  结果:

[ 'a', 'b' ]
[ 'a' ]
false
true

到这相信大家对JS构建对象有了一定的了解了!

 
原文地址:https://www.cnblogs.com/lilight/p/7520255.html