JavaScript面向对象之对象的创建(js的面向对象)

本文深入探讨JavaScript中对象的创建方式,包括使用Object构造函数、对象字面量、工厂模式、构造函数模式及原型模式,解析每种方法的优缺点。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

JavaScript作为一门面向对象的语言,对象当然一个很重要的概念,但是js又和其他面向对象语言又有区别,面向对象首先得有对象,有了对象才能“搞对象”吧,今天我们就从对象创建开始慢慢进入js面向对象的世界吧!
在面向对象语言语言都有一个标志,就是都有类的概念,通过类可以创建任意多个具有相同属性和方法的对象。而ECMAScript中没有类的概念,他的对象定义为“无序属性的集合,其属性可以包含基本值、对象或者函数”。

创建对象

创建对象的方法通常有以下几种,我们通过具体的例子来理解以下他们各自的优缺点吧:
(1)创建自定义对象的最简单方式Object构造函数表示:

var person =new Object();
person,name="cindy";
person.age=21;
person.job="qianduan";
person.sayName=function(){
	alert(this.name);
	};

(2)最直白的对象创建方法–对象字面量表示法:

var person= {  
	name:"cindy",
	age:21,
	job:"qianduan",
	sayName: funciton(){
		alert(this.name);		
	}
};

上述两种方式都是早期JavaScript开发人员经常使用的创建对象的方法,但是这些方式有个明显的缺点:使用同一个接口创建很多对象,会产生大量的重复代码!为了解决这个问题人们发明了工厂模式。接下来说一下工厂模式:
(3)工厂模式是软件工程领域一种广为人知的设计模式,顾名思义就是像工厂批量生产一样创建对象。由于JavaScript中没有类的概念,考虑用函数来封装以特定接口创建对象的细节,如下例子所示:

function createPerson(name,age,job){
	var person =new Object();
	person,name=name;
	person.age=age;
	person.job=job;
	person.sayName=function(){
		alert(this.name);
	};
	return person;
	var person1=createPerson("cindy",21,"qianduan");

上述代码通过函数接收参数来构建一个包含所有信息的Person对象,可以无数次调用,而每次都返回一个包含三个属性一个方法的对象。虽然他解决了大量重复代码的问题,但是每个被创建出来的对象都是Object对象,没有办法识别他的类型,所以就有另一个新的模式闪亮登场!!!
(4)构造函数模式:ECMAScript中的构造函数可用来创建特定类型的对象,把上述的例子重写如下:按照惯例构造函数的函数名都是大写

function Person(name,age,job){
	this.name=name;
	this.age=age;
	this.job=job;
	this.sayName=function(){
		alert(this.name);
		};		
}
var person1=new Person("cindy",21,"qinaduan");

在这个例子中,Person()函数取代了createPerson()函数,不同点是构造函数的方法里没有显式的创建对象,直接将属性和方法赋给了this对象,没有return语句,要创建Person的实例,必须使用new操作符。在这里补充一下new一个构造函数的对象会经历的四个步骤,也是面试常问的问题:
1.创建一个新对象
2.将构造函数的作用域赋给新对象,即this指向这个新对象
3.执行构造函数中的代码,为这个新对象添加属性
4.返回新对象
创建自定义的构造函数意味着将来可以将他的实例标识为一种特定的类型,这也是构造函数胜过工厂模式的地方。
同样的要是构造函数什么缺点都没有的话就不会出现新的方法啦,所以构造函数创建对象有什么缺点呢?使用构造函数的主要问题就是每个方法都要在每个实例上重新创建一遍,如果将上述例子再新建一个person2实例的话,person1和person2都有一个名为sayName()的方法,但那两个方法虽然存在的意义相同,却是不同的两个Function实例,然而创建两个完成相同任务的Function实例没有必要;况且有this对象在,根本不需要在执行代码前就把函数绑定在特定对象上,所以可以吧函数定义转移到构造函数外部来解决这个问题,如下代码所示:

function Person(name,age,job){
	this.name=name;
	this.age=age;
	this.job=job;
	this.sayName=sayName;
}
function sayName(){
		alert(this.name);
		};		
var person1=new Person("cindy",21,"qinaduan");

这样虽然解决了上述问题,又引发了新的问题真是一波三折啊。他将函数放在了全局作用域里,没有封装性又没有起到全局作用域的作用,并且污染了全局作用域的命名空间,所以出现了原型模式来解决这个问题。
(5)原型模式:我们创建的每一个函数都有一个prototype(原型)属性,这个属性指向一个对象也就是原型对象。,这个对象就可以用来存放所有实例共享的属性和方法。直接将属性和方法添加到函数的原型对象上,让他们成为公共的可访问的部分就可以保证所有实例对象使用的是同一组属性和同一组方法。如下的例子所示;

function Person(){

}
	Person.prototype.name="cindy";
	Person.prototype.age=21;
	Person.prototype.job="qianduan";
	Person.prototype.sayName=function(){
		alert(this.name);
		}
	var person1=new Person();
	person1.sayName();    //"cindy"
	var person2=new Person();
	person2.sayName();   //"cindy"
	alert(person1.sayName==person2.sayName);   //true

由上述可知,我们将sayName()方法和所有属性直接添加到了Person的prototype属性中,构造函数成了空函数,仍然通过构造函数来创建新对象,但是和构造函数模式不同的是,新对象的属性和方法是由所有实例共享的,因此person1和person2访问的都是同一组属性和同一个sayName()函数。
今天的分享就到这,下次接着原型对象继续~~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值