网站首页 > java教程 正文
点击右上方红色按钮关注“web秀”,让你真正秀起来
在JavaScript创建对象(一)——工厂模式留下了一个问题,就是创建一个对象怎么判断一个对象的类型。换句话说使用下面这种方式:
function createPerson(name, age, job){ var o = new Object(); o.name = name; o.age = age; o.job = job; o.sayName = function(){ console.log(this.name); } return o; }
只是函数的名字叫createPerson,其实返回的对象的本质还是一个Object。现在只能你说他是什么,他就是什么,有没有一种方法比如类似下面这样:
var p1 = createPerson('Javanx', 26, 'JavaScript'); if(p1 == Person){ console.log('p1是帅哥'); } if(p1 == Dog){ console.log('p1是美女'); }
在程序上有一种判断逻辑可以区分对象的类型呢?答案是有的,这就是本篇文章要讨论的构造函数模式。
现在使用构造函数模式改写上面的工厂模式:
function Person(name, age, job){ this.name = name; this.age = age; this.job = job; this.sayName = function(){ console.log(this.name); } } var p1 = new Person('Javanx', 26, 'JavaScript'); var p2 = new Person('lisi', 20, 'Java');
我们比较构造函数模式和工厂模式发现构造函数模式有以下不同:
- 没有显式的创建对象,如工厂模式 var o = new Object();
- 直接将属性和方法赋给了this,而不是o
- 没有return语句
- 创建对象使用new关键字,而不是直接调用函数
现在我们可以来讨论如何解决判断对象类型的问题了,很简单,可以使用如下代码:
console.log(p1.constructor == Person); //true console.log(p2.constructor == Person); //true
同理,判断一个对象是否是人,也可以这样:
function Person(name, age, job){ this.name = name; this.age = age; this.job = job; this.sayName = function(){ console.log(this.name); } } var d1 = new Person('Javanx', 26, 'JavaScript'); var d2 = new Person('James', 30, 'Java'); console.log(d1.constructor == Person); //true console.log(d2.constructor == Person); //true
这样就可以用代码在逻辑上判断一个对象的类型了。
检测对象的类型除了可以使用对象的constructor属性还可以使用instanceof关键字。JavaScript和Java一样,所有对象均继承自Object,使用instanceof可以检测到继承链,但是constructor不行,所以从这个角度来说instanceof更可靠一些,因为一个对象是子类型,当然也是父类型。看下面代码:
console.log(p1.constructor == Object); //false console.log(p1.constructor == Person); //true console.log(p1 instanceof Object); //true console.log(p1 instanceof Person); //true
至此构造函数函数不止具有了工厂模式的优点,还解决了工厂模式的缺点,那么构造函数模式有没有缺点呢?当然也是有的。 以上述p1、p2为例,这两个对象都具有sayName函数,而且功能也一样。在构造函数中sayName是一个指针, function(){alert(this.name)}是一个匿名函数,我们知道js中函数也是对象,每次创建对象都要执行构造函数,那么也就会创建一个匿名函数对象,若是创建若干个对象,那么就要创建若干个匿名函数对象,功能都相同,没必要不说,还占用内存。
通过以下代码可以说明p1的sayName和p2的sayName确实是两个实例。
console.log(p1.sayName == p2.sayName); //false
那么我们可以尝试像下面这样解决这个问题,把函数定义到构造函数之外:
function Person(name, age, job){ this.name = name; this.age = age; this.job = job; this.sayName = sayName; } function sayName(){ console.log(this.name); } var p1 = new Person('zhangsan', 18, 'JavaScript'); var p2 = new Person('lisi', 20, 'Java'); console.log(p1.sayName == p2.sayName); //true
这样虽然解决了多个函数做同一件事的问题,但是又带来了新的问题:定义在全局作用域中的函数实际上只能被某个对象调用,这让全局作用域有点名不副实。比如这里的sayName(),实际上是为Person准备的,但因为是定义在全局作用域所以可以直接调用sayName(),也就是window.sayName(), 那么此时的this.name就是window.name了,违背了定义的初衷。另一个问题是:如果Person上需要定义很多方法,那么就要定义很多个全局函数,若再加上Dog等等其他对象的方法,这些方法全都定义为全局函数,相互揉杂在一起,那么我们自定义的引用类型就丝毫没有封装性可言了。
那么,构造函数模式多个函数做同一件事的问题到底怎么解决呢?请看下一篇——原型模式。
公告
喜欢小编的点击关注,了解更多知识!
猜你喜欢
- 2024-10-17 Java|剖析类内的五类成员:属性、方法、构造器、代码块、内部类
- 2024-10-17 C++|构造、析构、成员(静态、非静态)函数、友元、全局函数
- 2024-10-17 JavaScript构造函数和原型:构造函数和原型 原创
- 2024-10-17 灵魂拷问:创建 Java 字符串,用""还是构造函数
- 2024-10-17 dart系列之:dart类中的构造函数(dart命名构造函数)
- 2024-10-17 Java面试题#构造函数和Setter哪种DI方式更好
- 2024-10-17 「php」construct() 函数介绍与使用方法详解
- 2024-10-17 为什么不允许使用 Java 静态构造函数?
- 2024-10-17 关于构造函数的Java面试问题(关于构造函数的java面试问题有哪些)
- 2024-10-17 编程语言Java如何创建对象,看完秒懂
你 发表评论:
欢迎- 07-15采用Oracle OSB总线进行服务注册和接入
- 07-15javaEE 新闻管理系统 oracle11+tomcat6
- 07-15从Oracle演进看数据库技术的发展(oracle数据库发展史)
- 07-15如何升级oracle数据库安全补丁(oraclepsu补丁升级)
- 07-15【权威发布】关于Oracle WebLogic Server未授权远程代码执行高危漏洞的预警通报
- 07-15【mykit-data】 数据库同步工具(数据库表同步工具)
- 07-15[Java速成] 数据库基础,Connector/J、JDBC、JPA的关系(day 7)
- 07-15Google前工程主管“入住”Oracle(google浏览器找不到以前的书签)
- 最近发表
-
- 采用Oracle OSB总线进行服务注册和接入
- javaEE 新闻管理系统 oracle11+tomcat6
- 从Oracle演进看数据库技术的发展(oracle数据库发展史)
- 如何升级oracle数据库安全补丁(oraclepsu补丁升级)
- 【权威发布】关于Oracle WebLogic Server未授权远程代码执行高危漏洞的预警通报
- 【mykit-data】 数据库同步工具(数据库表同步工具)
- [Java速成] 数据库基础,Connector/J、JDBC、JPA的关系(day 7)
- Google前工程主管“入住”Oracle(google浏览器找不到以前的书签)
- Oracle数据库云服务系列新增前所未有的企业级功能
- 直播预告丨如何实现Oracle存储过程到java的一键转化
- 标签列表
-
- java反编译工具 (77)
- java反射 (57)
- java接口 (61)
- java随机数 (63)
- java7下载 (59)
- java数据结构 (61)
- java 三目运算符 (65)
- java对象转map (63)
- Java继承 (69)
- java字符串替换 (60)
- 快速排序java (59)
- java并发编程 (58)
- java api文档 (60)
- centos安装java (57)
- java调用webservice接口 (61)
- java深拷贝 (61)
- 工厂模式java (59)
- java代理模式 (59)
- java.lang (57)
- java连接mysql数据库 (67)
- java重载 (68)
- java 循环语句 (66)
- java反序列化 (58)
- java时间函数 (60)
- java是值传递还是引用传递 (62)
本文暂时没有评论,来添加一个吧(●'◡'●)