javascript 面向对象(多种创建对象的方式)
创建对象
第一种:基于Object对象
var person = new Object();
person.name = 'My Name';
person.age = 18;
person.getName = function(){
return this.name;
}
第二种:对象字面量方式(比较清楚的查找对象包含的属性及方法)
var person = {
name : 'My name',
age : 18,
getName : function(){
return this.name;
}
}
使用Object构造函数或对象字面量都可以创建对象,但缺点是创建多个对象时,会产生大量的重复代码,因此下面介绍可解决这个问题的创建对象的方法
1、工厂模式
function createPerson(name, age) {
var o = new Object();
o.name = name;
o.age = age;
o.getAge = function () {
return this.age;
};
return o;
}
var person = createPerson('张三', 23);
console.log(person.name); //'张三'
console.log(person.age); //23
console.log(person.getAge()); //23
缺点:创建对象交给一个工厂方法来实现,可以传递参数,但主要缺点是无法识别对象类型,因为创建对象都是使用Object的原生构造函数来完成的。
2、构造函数模式
function Person(name, age) {
this.name = name;
this.age = age;
this.getAge = function () {
return this.age;
};
}
var person = new Person('张三', 23);
console.log(person.name); //'张三'
console.log(person.age); //23
console.log(person.getAge()); //23
alert(person instanceof Person); //true;
alert(person instanceof Object); //true;
2.1 使用自定义的构造函数(与普通函数一样,只是用它来创建对象),定义对象类型(如:Person)的属性和方法。它与工厂方法区别在于:
- 没有显式地创建对象
- 直接将属性和方法赋值给this对象;
- 没有return语句;
此外,要创建Person的实例,必须使用new关键字,以Person函数为构造函数,传递参数完成对象创建;
2.2 要创建 Person 的新实例,必须使用 new 操作符。以这种方式调用构造函数实际上会经历以下 4个步骤:
(1) 创建一个新对象;
(2) 将构造函数的作用域赋给新对象(因此 this 就指向了这个新对象);
(3) 执行构造函数中的代码(为这个新对象添加属性);
(4) 返回新对象。
在前面例子的最后, person1 和 person2 分别保存着 Person 的一个不同的实例。这两个对象都有一个 constructor (构造函数)属性,该属性指向 Person ,如下所示。
alert(person1.constructor == Person); //true
alert(person2.constructor == Person); //true
对象的 constructor 属性最初是用来标识对象类型的。
创建自定义的构造函数意味着将来可以将它的实例标识为一种特定的类型;而这正是构造函数模式胜过工厂模式的地方。
function Person(name, age) {
this.name = name;
this.age = age;
this.getAge = new Function ("return this.age"); //和上面是一样的,会重复创建多个函数
}
缺点:上述代码,创建多个实例时,会重复调用new Function();创建多个函数实例,这些函数实例还不是一个作用域中,当然这一般不会有错,但这会造成内存浪费。
3、原型模式
function Person(name) {
this.name = name;
}
Person.prototype.age = 23;
Person.prototype.getAge = function () {
return this.age;
};
var person = new Person('张三');
console.log(person.name); //'张三'
console.log(person.age); //23
console.log(person.getAge()); //23
JS每个函数都有一个prototype(原型)属性,这个属性是一个指针,指向一个对象,它是所有通过new操作符使用函数创建的实例的原型对象。
原型对象最大特点是,所有对象实例共享它所包含的属性和方法,也就是说,所有在原型对象中创建的属性或方法都直接被所有对象实例共享。
实例属性或方法的访问过程是一次搜索过程:
- 首先从对象实例本身开始,如果找到属性就直接返回该属性值;
- 如果实例本身不存在要查找属性,就继续搜索指针指向的原型对象,在其中查找给定名字的属性,如果有就返回;
基于以上分析,原型模式创建的对象实例,其属性是共享原型对象的;但也可以自己实例中再进行定义,在查找时,就不从原型对象获取,而是根据搜索原则,得到本实例的返回;简单来说,就是实例中属性会屏蔽原型对象中的属性;
可以通过使用hasOwnProperty()方法来判断,属性是实例本身的,还是原型上的。
person.hasOwnProperty("name"); //true
person.hasOwnProperty("age"); //false
缺点:最主要是当对象的属性是引用类型时,它的值是不变的,总是引用同一个外部对象,所有实例对该对象任何一个地方产生的改动会引起其他实例的变化。
function Person(name) {
this.name = name;
}
Person.prototype.age = 23;
Person.prototype.color = ['red', 'yellow'];
var person1 = new Person('张三');
console.log(person1.name); //'张三'
console.log(person1.color); //["red", "yellow"]
person1.color.push('black');
var person2 = new Person('李四');
console.log(person2.name); //'李四'
console.log(person2.color); //["red", "yellow", "black"] //person1的修改影响了person2
4、组合使用构造函数模式及原型模式
目前最为常用的定义类型方式,是组合使用构造函数模式与原型模式。
构造函数模式用于定义实例的属性,而原型模式用于定义方法和共享的属性。结果,每个实例都会有自己的一份实例属性的副本,但同时又共享着对方方法的引用,最大限度的节约内存。
此外,组合模式还支持向构造函数传递参数,可谓是集两家之所长。
function Person(name, age) {
this.name = name;
this.age = age;
this.color = ['red', 'yellow'];
}
Person.prototype = {
constructor : Person, //原型字面量形式会将对象的constructor变Object,此外强制指回Person;
getAge : function () {
return this.age;
}
};
var person1 = new Person('张三', 23);
person1.color.push('black');
console.log(person1.name); //张三
console.log(person1.color); //["red", "yellow", "black"]
console.log(person1.getAge()); //23
var person2 = new Person('李四', 24);
console.log(person2.name); //李四
console.log(person2.color); //['red','yellow']
console.log(person2.getAge()); //24
5、动态原型模式
组合模式中实例属性与共享方法(由原型定义)是分离的,这与纯面向对象语言不太一致;动态原型模式将所有构造信息都封装在构造函数中,又保持了组合的优点。其原理就是通过判断构造函数的原型中是否已经定义了共享的方法或属性,如果没有则定义,否则不再执行定义过程。该方式只原型上方法或属性只定义一次,且将所有构造过程都封装在构造函数中,对原型所做的修改能立即体现所有实例中:
function Person(name, age, job) {
this.name = name;
this.age = age;
this.job = job;
this.lessons = ['Math', 'Physics'];
}
if (typeof this.getName != 'function') {//通过判断实例封装
Person.prototype = {
constructor: Person,//原型字面量方式会将对象的constructor变为Object,此外强制指回Person
getName: function () {
return this.name;
}
}
}
var person1 = new Person('Jack', 19, 'SoftWare Engneer');
person1.lessons.push('Biology');
var person2 = new Person('Lily', 39, 'Mechanical Engneer');
alert(person1.lessons);//Math,Physics,Biology
alert(person2.lessons);//Math,Physics
alert(person1.getName === person2.getName);//true,//共享原型中定义方法
javascript 面向对象(多种创建对象的方式)的更多相关文章
- js面向对象 多种创建对象方法小结
转自js面向对象 多种创建对象方法小结 1.对象字面量 var clock={ hour:12, minute:10, second:10, showTime:function(){ alert(th ...
- Javascript面向对象之创建对象
面向对象的语言具有一个共同的标志,那就是具有“类”的概念,但是在javascript中没有类的概念,在js中将对象定义为“无序属性的集合,其属性可以包含基本值,对象或者函数”,即其将对象看作是一组名值 ...
- javascript三种创建对象的方式
javascript是一种“基于prototype的面向对象语言“,与java有非常大的区别,无法通过类来创建对象.那么,既然是面象对象的,如何来创建对象呢? 一.通过”字面量“方式创建. 方法:将成 ...
- JavaScript面向对象实现
JavaScript面向对象实现 一:面向对象三大特征 继承,封装,多态! 二:JavaScript自定义对象 创建对象的方式: 方式1,对象初始化器方式: <script type=&quo ...
- 轻松学习JavaScript十二:JavaScript基于面向对象之创建对象(一)
这一次我们深入的学习一下JavaScript面向对象技术,在学习之前,必要的说明一下一些面向对象的一些术语. 这也是全部面对对象语言所拥有的共同点.有这样几个面向对象术语: 对象 ECMA-262把对 ...
- JavaScript 常见创建对象的方式
JavaScript 有哪几种创建对象的方式? javascript创建对象简单的说,无非就是使用内置对象或各种自定义对象,当然还可以用JSON:但写法有很多种,也能混合使用. (1)对象字面量的方式 ...
- javascript中创建对象的方式总结
javascript中创建对象的方式总结 具体代码如下: //创建对象的方式: //创建方式一 var person=new Object(); person.name='jack'; person. ...
- JavaScript高级特性-创建对象的九种方式
1. 对象字面量 通过这种方式创建对象极为简单,将属性名用引号括起来,再将属性名和属性值之间以冒号分隔,各属性名值对之后用逗号隔开,最后一个属性不用逗号隔开,所有的属性名值对用大括号括起来,像这样: ...
- Javascript面向对象——创建对象、构造函数的原型
Javascript面向对象--创建对象.构造函数的原型 其实:JavaScript中的创建类,就是创建一个构造函数,在创建对象时用到new这个关键字, 一.创建对象 1.函数创建对象 functio ...
随机推荐
- 【javaweb学习笔记】WEB01_HTML
案例一:网站信息显示页面1.什么是HTML?(Hyper Text Markup Language:超文本标记语言) 超文本:功能比普通文本更加强大 标记语言:使用一组标签对内容进行描述的一门语言(它 ...
- phpmailer发送邮件服务
获取开源的phpmail类 开启stmp服务登录126/163邮箱 ->设置->POPS/SMTP/IMAP(开启需要的服务,并点击保存,初次使用会要求设置一个授权码) 测试 <?p ...
- 【转】高斯-克吕格投影与UTM投影异同
高斯-克吕格(Gauss-Kruger)投影与UTM投影(Universal Transverse Mercator,通用横轴墨卡托投影)都是横轴墨卡托投影的变种,目前一些国外的软件或国外进口仪器的配 ...
- [UWP]新控件ColorPicker
1. 前言 Fall Creators Update中提供了一个新得ColorPicker控件,解决了以前选择颜色只能用Combo Box的窘境. 2. 一个简单的例子 <ColorPicker ...
- 老凡原创PHPcms发布上架chinaz
FanCms内容管理系统(3网兼容) FanCms内容管理系统(3网兼容)核心使用CodeIgniter框架.使用SQlite数据库,不需要安装,上传到任意支持PHP的空间,就能使用.高级URL自定义 ...
- HTML5详解(一)
本文最初发表于博客园,并在GitHub上持续更新前端的系列文章.欢迎在GitHub上关注我,一起入门和进阶前端. 以下是正文. HTML5的介绍 Web 技术发展时间线 1991 HTML 1994 ...
- Spring源码解析一(框架梳理)
整体架构 打算开始写这个系列,不为上首页,也不为博取多少关注,只有一个目的:梳理知识,扩充思路:废话不多,开始吧.第一步,大家去spring的官方github下面去下载它的源码,具体的自己谷歌,我已经 ...
- GO开发[六]:golang反射(reflect)
反射 反射:可以在运行时动态获取变量的相关信息 Import ("reflect") reflect.TypeOf,获取变量的类型,返回reflect.Type类型 refle ...
- Using Custom Domains With IIS Express In Asp.Net Core
IIS Express是一个Mini版的IIS,能够支持所有的Web开发任务,但是这种设计有一些缺陷,例如只能通过localhost:<port>的方式来访问我们的应用程序,看起来就有点不 ...
- 转换number为千分位计数形式js
JS实现转换千分位计数 350000.00-------350,000.00 var num=0;function format (num) { return (num.toFixed(2) + '' ...