一、概述

  虽然对象字面量可以用来创建对象,但在创建多个类似的对象时,不够优雅,不符合DRY原则。

二、创建对象

  有以下几种模式:

  1.工厂模式

  2.构造函数模式

  3.原型模式

  4.组合构造函数和原型模式(推荐)

5.动态原型模式 (推荐)

6.稳妥构造函数模式 

  1.工厂模式  

function createPerson(name,age,job)
{
var o={
name:name,
age:age,
job:job,
saySelf:function(){
console.log(this.name+this.age+this.job);
}
};
return o;
}
var person=createPerson("我是工厂模式建的",20,"ape");
person.saySelf();

优点:可创建多个相似对象。

缺点:无法识别对象。

2.构造函数模式

  

function Person(name,age,job)
{
this.name=name;
this.age=age;
this.job=job;
this.saySelf=function(){
console.log(this.name+this.age+this.job);
}
}
var person=new Person("构造函数模式",20,"ape");
person.saySelf();

    特点:

    1. 没有显式的创建对象,直接将属性和方法给了this;
    2. 没有return;
    3. 函数名大写,一般构造函数名大写;      

    要创建Person的实例,必须使用new操作符,Person的实例都有constructor属性,该属性指向Person();

    

        console.log(person.constructor===Person)//true
console.log(person instanceof Person) //true 推荐

    自定义构造函数可以标识为一种特定类型。

    任何函数,只要通过new调用,就可以当作构造函数,构造函数与普通函数没什么两样。

    优点:可识别类型。

    缺点:每个方法要在每个实例上重建一遍,工厂模式也有此类问题。

console.log(person.saySelf===person2.saySelf);//false

  3.原型模式

    

    (function(){
function Person()
{
}
Person.prototype.name='原型模式';
Person.prototype.age='28';
Person.prototype.job='Ape';
Person.prototype.saySelf=function(count){
if(count)
console.log(count+":"+this.name+this.age+this.job);
else
console.log(this.name+this.age+this.job);
}
var person=new Person();
var person2=new Person();
person.saySelf();
person2.saySelf();
console.log(1,person.saySelf===person2.saySelf);//true
console.log(2,Person.prototype.isPrototypeOf(person));//true
console.log(3,Object.prototype.isPrototypeOf(person));//true
console.log(4,Object.getPrototypeOf(person)===Person.prototype);//true
console.log(8,person.name);
person.name="看看变不变";
person.saySelf(9);//9:看看变不变28Ape
person2.saySelf(10);//10:原型模式28Ape
delete person.name;
person.saySelf(11);//11:原型模式28Ape
person.__proto__.name="现在肯定变了";
person2.saySelf();//现在肯定变了28Ape 只在Firefox、Safari、Chrome中有效
})();

当添加一个属性时,这个属性就会屏蔽原型对象的同名属性。但是可以通过delete删除实例属性,让实例重新可以访问这个属性。说话是苍白的,看上面代码。

通过hasOwnProperty()可判断属性是否是实例自己的属性(区别于从原型上继承来的)。

        console.log(person.hasOwnProperty("name"));//true
delete person.name;
console.log(person.hasOwnProperty("name"));//false

那么,怎么检测某个属性是否是实例的属性呢,用in操作符,无论属性在实例中还是在原型中,都返回true

        console.log("in","name" in person);//true
delete person.name;
console.log("in","name" in person);//true

    可用Object.keys()方法,返加一个所有可枚举属性的的字符串数组。

    如果想得到,全部的属性可用Object.getOwnPropertyNames();

    两个方法的共同点:均列举出自有属性,不查找原型链;

           不同点:Object.keys()方法返回可枚举属性,Object.getOwnPropertyNames()返回所有属性的keys。

        person2.sex="男";
console.log(Object.keys(Person.prototype).join(";"));//name;age;job;saySelf
console.log(Object.getOwnPropertyNames(Person.prototype).join(";"));//constructor;name;age;job;saySelf
console.log(Object.keys(person2).join(";"));//sex
console.log(Object.getOwnPropertyNames(person2).join(";"));//sex

    原型的动态性,这个很好理解,原型只是引用用,动态添加,当然可用。

    但是,实例化一个对象后,再去重写一个原型,实例仍然指向原来的原型。

 //原型的动态性
(function(){
function Person()
{
}
Person.prototype.name='原型模式';
Person.prototype.age='28';
Person.prototype.job='Ape';
Person.prototype.saySelf=function(count){
if(count)
console.log(count+":"+this.name+this.age+this.job);
else
console.log(this.name+this.age+this.job);
}
var person=new Person();
console.log(Object.getOwnPropertyNames(person.__proto__).join(";"));
Person.prototype={
constructor:Person,
sex:"汉子"
}
var person2=new Person();
console.log(Object.getOwnPropertyNames(person.__proto__).join(";"));
console.log(Object.getOwnPropertyNames(person2.__proto__).join(";"));
})();

  

  优点:共享方法,可用isPrototypeOf检测是否是原型,在ES5中,可用getPrototypeOf得到原型。

  缺点:不能拥有自己的属性。这个致命的缺点导致基本没有人用原型模式。

4.组合构造函数和原型模式。

function Person(name,age,job)
{
this.name=name;
this.age=age;
this.job=job;
}
Person.prototype={
constructor:Person,
saySelf:function()
{
console.log(this.name+this.age+this.job);
}
};
Person.static=function()
{
console.log("这是一个静态方法");
}
var person=new Person();
Person.static();//这是一个静态方法
person.static();//Uncaught TypeError: undefined is not a function

    这个模式解决了以上所有的缺点,同时具有以上所有的优点,是在javascript应用最广泛的创建自己定义类型的方法。是用来定义定义引用类型的一种默认模式。

  5.动态原型模式 

    //动态原型模式
(function(){
function Person(name,age,job)
{
this.name=name;
this.age=age;
this.job=job;
if(typeof this.saySelf!=="function") {
Person.prototype.saySelf = function ()
{
console.log(this.name + this.age + this.job);
}
         
}
} var person=new Person("工厂模式",20,"frontEndpe");
var person2=new Person("工厂模式Ac",20,"frontEndApe");
person.saySelf();
person2.saySelf();
})();

优点:把原型封装构造函数中。

缺点:每个实例化都进行一次判断(这个也不算什么)。

  6.稳妥构造函数模式  

    //稳妥构造函数模式
(function(){
function Person(name)
{
var o={};
//可以添加私有的方法和变量
o.sayName=function()
{
console.log(name);
}
return o;
} var person=Person("工厂模式");
var person2=Person("工厂模式Ac");
person.sayName();
person2.sayName();
var say=person2.sayName;
say(); })();

稳妥对象:没有公共属性的对象。

name属性只有sayName()闭包访问

三、总结

  综合以上,推荐使用 4.组合构造函数和原型模式和5.动态原型模式。

  它们都有以下优点:

  1.都可以识别对象 。

  2.都可以有自己的属性值(constructor) 和共享的属性(prototype)

四、代码

<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
</head>
<body>
<script>
"use strict";
(function(){
// 工厂模式
(function(){
function createPerson(name,age,job)
{
var o={
name:name,
age:age,
job:job,
saySelf:function(){
console.log(this.name+this.age+this.job);
}
};
return o;
}
var person=createPerson("工厂模式",20,"ape");
var person2=createPerson("工厂模式2",20,"ape");
console.log(person.saySelf===person2.saySelf);
person.saySelf();
});//();
// 构造函数模式
(function(){
function Person(name,age,job)
{
this.name=name;
this.age=age;
this.job=job;
this.saySelf=function(){
console.log(this.name+this.age+this.job);
}
}
var person=new Person("构造函数模式",20,"ape");
var person2=new Person("构造函数模式2",20,"ape");
person.saySelf();
console.log(person.constructor===Person);//true
console.log(person instanceof Person); //true 推荐
console.log(person.saySelf===person2.saySelf);//false
});//();
//原型模式
(function(){
function Person()
{
}
Person.prototype.name='原型模式';
Person.prototype.age='28';
Person.prototype.job='Ape';
Person.prototype.saySelf=function(count){
if(count)
console.log(count+":"+this.name+this.age+this.job);
else
console.log(this.name+this.age+this.job);
}
var person=new Person();
var person2=new Person();
person.saySelf();
person2.saySelf();
console.log(1,person.saySelf===person2.saySelf);//true
console.log(2,Person.prototype.isPrototypeOf(person));//true
console.log(3,Object.prototype.isPrototypeOf(person));//true
console.log(4,Object.getPrototypeOf(person)===Person.prototype);//true
console.log(5,person.name);
person.name="看看变不变";
person.saySelf(9);//9:看看变不变28Ape
person2.saySelf(10);//10:原型模式28Ape
console.log(person.hasOwnProperty("name"));//true
console.log("in","name" in person);//true
delete person.name;
console.log("in","name" in person);//true
console.log(person.hasOwnProperty("name"));//false
person.saySelf(11);//11:原型模式28Ape
person.__proto__.name="现在肯定变了";
person2.saySelf();//现在肯定变了28Ape 只在Firefox、Safari、Chrome中有效
person2.sex="男";
console.log(Object.keys(Person.prototype).join(";"));//name;age;job;saySelf
console.log(Object.getOwnPropertyNames(Person.prototype).join(";"));//constructor;name;age;job;saySelf
console.log(Object.keys(person2).join(";"));//sex
console.log(Object.getOwnPropertyNames(person2).join(";"));//sex
});//();
//原型的动态性
(function(){
function Person()
{
}
Person.prototype.name='原型模式';
Person.prototype.age='28';
Person.prototype.job='Ape';
Person.prototype.saySelf=function(count){
if(count)
console.log(count+":"+this.name+this.age+this.job);
else
console.log(this.name+this.age+this.job);
}
var person=new Person();
console.log(Object.getOwnPropertyNames(person.__proto__).join(";"));
Person.prototype={
constructor:Person,
sex:"汉子"
}
var person2=new Person();
console.log(Object.getOwnPropertyNames(person.__proto__).join(";"));
console.log(Object.getOwnPropertyNames(person2.__proto__).join(";"));
});//();
//组合构造函数和原型模式。 最常用
(function(){
function Person(name,age,job)
{
this.name=name;
this.age=age;
this.job=job;
}
Person.prototype={
constructor:Person,
saySelf:function()
{
console.log(this.name+this.age+this.job);
}
};
Person.static=function()
{
console.log("这是一个静态方法");
}
var person=new Person();
Person.static();//这是一个静态方法
person.static();//Uncaught TypeError: undefined is not a function
});//();
//动态原型模式
(function(){
function Person(name,age,job)
{
this.name=name;
this.age=age;
this.job=job;
if(typeof this.saySelf!=="function") {
Person.prototype.saySelf = function ()
{
console.log(this.name + this.age + this.job);
} }
} var person=new Person("工厂模式",20,"frontEndpe");
var person2=new Person("工厂模式Ac",20,"frontEndApe");
person.saySelf();
person2.saySelf();
});//();
//稳妥构造函数模式
(function(){
function Person(name)
{
var o={};
//可以添加私有的方法和变量
o.sayName=function()
{
console.log(name);
}
return o;
} var person=Person("工厂模式");
var person2=Person("工厂模式Ac");
person.sayName();
person2.sayName();
var say=person2.sayName;
say();
});//();
})();
</script>
</body>
</html>

Javascript对象创建的更多相关文章

  1. 【JavaScript学习】JavaScript对象创建

    1.最简单的方法,创建一个对象,然后添加属性 var person = new Object(); person.age = 23; person.name = "David"; ...

  2. 深入JavaScript对象创建的细节

    最近深入学习javascript后,有个体会:面向对象的方式编程才是高效灵活的编程,也是现在唯一可以让代码更加健壮的编程方式.如果我们抛开那些玄乎的抽象出类等等思想,我自己对面向对象的从写程序的角度理 ...

  3. JavaScript 对象创建

    tips: JavaScript 除了null和undefined之外,其他变量都可以当做对象使用. JavaScript 的基本数据类型有:number boolean string null  u ...

  4. JavaScript对象创建的几种方式

    1 工厂模式 1.1 创建 function createFruit(name,colors) { var o = new Object(); o.name = name; o.colors = co ...

  5. Javascript 对象创建多种方式 原型链

    一.对象创建 1.new Object 方式 直接赋上属性和方法 var obj = new Object(); obj.name = '娃娃'; obj.showName = function(){ ...

  6. JavaScript对象创建,继承

    创建对象 在JS中创建对象有很多方式,第一种: var obj = new Object(); 第二种方式: var obj1 = {};//对象直面量 第三种方式:工厂模式 function Per ...

  7. javascript对象创建方式

    工厂模式 在ECMAscript中无法创建类,所以开发人员就发明了一种函数,用函数来封装,以特定接口创建对象的细节,如下面的例子所示: function createPerson(name,age,j ...

  8. JavaScript—对象创建方式

    JavaScript 也是面向对象的语言(oop) 之前学JavaScript 没有学对象.现在做下笔记 创建对象的方式: 1.  对象字面量 const hero = { name: '吕布', w ...

  9. [JavaScript]对象创建方法

    1.使用Object或对象字面量创建对象 (1)使用Object创建对象 var cat= new Object(); cat.name = "Tom"; cat.color= & ...

随机推荐

  1. 人人都是 DBA(I)SQL Server 体系结构

    在了解 SQL Server 数据库时,可以先从数据库的体系结构来观察.SQL Server 的体系结构中包含 4 个主要组成部分: 协议层(Protocols) 关系引擎(Relational En ...

  2. 【T-SQL基础】03.子查询

    以前总是追求新东西,发现基础才是最重要的,今年主要的目标是精通SQL查询和SQL性能优化. 本系列[T-SQL基础]主要是针对T-SQL基础的总结. [T-SQL基础]01.单表查询-几道sql查询题 ...

  3. Host is not allowed to connect to this MySQL server 错误的处理方法

    1. mysql>use mysql; mysql>update user set host = '%' where user = 'root'; mysql>select host ...

  4. java提高篇(七)-----关键字static

    一. static代表着什么 在Java中并不存在全局变量的概念,但是我们可以通过static来实现一个“伪全局”的概念,在Java中static表示“全局”或者“静态”的意思,用来修饰成员变量和成员 ...

  5. XCode v8.11 重量级分表分库(无视海量数据)

    XCode天生就有分表分库功能,设计于2005年!历时9年,这是分表分库功能第一次针对性正式更新. 在XCode里面,分表分库非常简单,在操作数据(查询/更新)前修改Meta.ConnName/Met ...

  6. Qt 设置应用程序图标

    Qt4设置应用程序图标 将一个ico图标放在资源文件夹下; 然后建立txt,输入 IDI_ICON1 DISCARABLE "myico.ico"; 保存文件,将其后缀改为.rc; ...

  7. 程序员DNS知识指南

    本次内容比较hardcore,非科班出身可能会有理解障碍,可以考虑不用挣扎,直接放弃.毕竟普通驾驶员是不需要理解内燃机原理和曲轴如何做功的,所谓术业有专攻也,能看完的不是同行就是真爱~ 引 DNS对于 ...

  8. 基础才是重中之重~LazyInitializer.EnsureInitialized对属性实现化的性能优化

    回到目录 LazyInitializer.EnsureInitialized是frameworks4.0引入的新东西,实现对属性延时初始化的功能,它作用在System.Threading命名空间下,所 ...

  9. MyBatis学习总结(八)——Mybatis3.x与Spring4.x整合

    一.搭建开发环境 1.1.使用Maven创建Web项目 执行如下命令: mvn archetype:create -DgroupId=me.gacl -DartifactId=spring4-myba ...

  10. 转载:Spring AOP (上)

    工 作忙,时间紧,不过事情再多,学习是必须的.记得以前的部门老大说过:“开发人员不可能一天到晚只有工作,肯定是需要自我学习.第一:为了更充实自己,保 持进步状态.第二:为了提升技术,提高开发能力.第三 ...