前言:
本篇博客目的在于给大家分享一下JS中如何去创建对象,以及创建对象的方法,让大家以后可以使用JS快乐的创建对象,以及在合适的场景使用合适的方式创建对象。
JS中的对象概念:
在JS中,我们把对象定义为:“无序属性的集合,值可以包含为基本值,对象,或者函数”,我们可以理解为对象就是一组没有特定顺序的值!
每个对象都是基于一个引用类型创建的(引用类型可以是 原生类型,也可以是我们自定义的类型),对象的每个属性和方法都有名字,并且每个名字都有一个值,(大家可以理解为键值对)。
JS中创建对象的方式:
实例化Object创建对象:
var person = new Object(); //实例化一个Object类型的对象
person.name = 'Sam'; //添加名字属性
person.age = 22; //添加年龄属性
person.job = 'Web Enginner';//添加属性
person.sayName = function () { //添加一个方法
console.log(this.name); //打印名字
}
person.sayName();
上边是创建对象的方式是最早期的JS开发人员创建对象的方式,看着代码看似很清晰,但是太过繁琐了,如果有多个person的话,那编写代码的画风就是 复制+粘贴大法了。并且如果粘贴代码漏掉一个属性,后期运行处错也是让人很难受的。。
对象字面量创建对象:
var person = {
name: 'Sam', //添加名字属性
age: 22, //添加年龄属性
job: 'Web Enginner',//添加属性
sayName: function () { //添加一个方法
console.log(this.name);
}
}
person.sayName(); //调用sayName方法
对象字面量创建对象这种方法创建对象将属性和方法包裹了起来,这样我们在编写代码的时候大概率就不会少写属性和方法了,但是如果同一种对象有多个,那么创建对象依然很麻烦,冗余代码还是很多。。
工厂模式创建对象:
function createperson(name, age, job) {
var o = new Object(); //显示的去创建一个对象 o
o.name = name, //添加名字属性
o.age = age, //添加年龄属性
o.job = job,//添加属性
o.sayName = function () { //添加一个方法
console.log(this.name);
}
return o;
}
var person1 = createperson('Sam', 22, "Web Engineer");
var person2 = createperson('Halen', 20, "Software Engineer");
person1.sayName(); //调用sayName方法
person2.sayName(); //调用sayName方法
console.log(person1 instanceof Object); // person1 是不是 Object类型 返回 true
上边的代码我们使用了软件工程领域大名鼎鼎的 “工厂模式”,工厂模式将创建对象的具体过程抽象了出来,但是JS中没有类的概念,因此我们就使用函数的方式来实现类的功能,使用函数来封装创建对象的细节。
我们使用工厂模式就可以非常快速的创建指定的对象了,但是大家仔细看代码会发现我们内部其实是实例化了一个Object类型的对象,虽然我们可以使用工厂模式创建多个相似的对象,但是类型却都是Object类型,这就很让人难受了。。
构造函数模式:
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('Sam', 22, "Web Engineer");
var person2 = new Person('Halen', 20, "Software Engineer");
person1.sayName(); //调用sayName方法
person2.sayName(); //调用sayName方法
console.log(person1 instanceof Person); // person1 是不是 Person类型 返回 true
console.log(person1 instanceof Person); // person1 是不是 Person类型 返回 true
console.log(person1.sayName == person2.sayName) //false, 对象的方法不是同一个
我们通过Person()函数来替代了createPerson()函数来创建对象,我们没有显示的去创建对象,而是直接将属性和方法复制给了this对象,最重要的是我们可以判断对象的类型了。
但是仔细查看上边的代码,我们会发现 sayName方法在每个对象中都要重新创建一遍,一样的功能我们却每一个对象中都要创建一遍,这就是构造函数难以克服的缺点。
我们按照惯例将构造函数的第一个字母大写,来和普通的非构造函数加以区别(非构造函数小写字母开头),因为JS中构造函数本身也是函数,为了加以区别,我们将构造函数开头大写。
暂时解决对象相同方法创建多个的办法:
function Person(name, age, job) {
this.name = name, //添加名字属性
this.age = age, //添加年龄属性
this.job = job,//添加属性
this.sayName = sayName;//单独定义的方法赋值给对象
}
function sayName() { //创建一个方法
console.log(this.name);
}
var person1 = new Person('Sam', 22, "Web Engineer");
var person2 = new Person('Halen', 20, "Software Engineer");
person1.sayName(); //调用sayName方法
person2.sayName(); //调用sayName方法
console.log(person1.sayName == person2.sayName) //true, 对象的方法是同一个
我们通过把sayname()函数的定义放到了构造函数的外部,因为在外边定义的函数默认是全局的,这样我们每个实例化出来的对象就可以都引用同一个对象了。
但是仔细一想我们会发现,sayName函数只能给某个对象调用,这不是我们想要的,并且如果我们需要定义很多方法的话就需要创建很多全局函数,尴尬的是我们定义的全局函数还都是直接注册到了 Window上边,那么我们直接打印Window对象就可以发现所有的全局函数,这就破坏了封装性,这时候我们就需要使用原型模式来解决这个问题。
JS使用New操作符创建对象的四个步骤:
-
创建新对象
-
将构造函数作用域赋值给新对象(this指向这个新对象)
-
为新对象添加属性
-
返回这个对象
原型模式:
function Person() { };
Person.prototype.name = 'Sam';
Person.prototype.age = 22;
Person.prototype.job = 'Web Engineer';
Person.prototype.sayName = function () {
console.log(this.name);
}
var person1 = new Person();
var person2 = new Person();
person1.sayName(); // Sam
person2.sayName(); // Sam
console.log(person1.sayName == person2.sayName) //true, 对象的方法是同一个
上边代码中我们创建的空的Person()函数会带一个 prototype(原型)属性,这个属性是一个指针,指向一个对象(原型对象),原型对象中可以存储特定类型共享的属性和方法,这样我们就可以将属于某类对象的全局属性和方法存到指定类型的原型对象上,这样方便实例对象使用,而不会有破坏封装的问题。
什么是原型对象:
在JS中,每当我们创建一个新的函数,JS就会根据特定的规则去创建 prototype属性,这属性来指向原型对象。
默认情况下,所有的原型对象都会有一个constructor属性,这个属性指向prototype所在的函数,就像上边的例子,Person.prototype.constructor 指向了Person。
在我们调用构造函数实例化一个对象以后,对象内部会有一个[[prototype]]属性也指向构造函数的原型对象,在谷歌浏览器中可以通过 _proto_来访问原型对象!
原型对象的特性:
我们可以向原型对象中添加属性和方法,但是不能通过对象实例重写原型对象的值,我们如果直接给实例对象添加和原型对象一样的属性名,那么以后我们只可以读取实例对象的同名属性,而不会再去读取原型对象的属性,但是我们可以通过delete方法删除实例对象的同名属性,来恢复读取原型对象的属性。
function Person() { };
Person.prototype.name = 'Sam';
Person.prototype.age = 22;
Person.prototype.job = 'Web Engineer';
Person.prototype.sayName = function () {
console.log(this.name);
}
var person1 = new Person();
var person2 = new Person();
person1.name = 'Helan';
console.log(person1.name); //Helan
console.log(person2.name); //Sam
delete person1.name; //删除实例对象的属性
console.log(person1.name); //重新读取原型对象中的值 Sam
总结:
上边内容主要展示了我们在JS中创建对象的方法:实例化Object、对象字面量、工厂模式、构造函数模式、原型模式,这5中创建对象的方法,我们可以根据我们具体的场景来选择合适的创建对象的方法,希望这篇文章可以让大家在以后创建对象时候不在纠结使用哪个办法!