您的位置:首页 > Web前端 > JavaScript

Javascript面向对象-创建对象

2019-04-18 16:41 435 查看

1、通过”字面量“方式创建(推荐)

var obj = { };  //创建一个空对象
var arr=[];  //创建一个空数组对象

创建语法

var p1={
"true name":"Lily",
'age':18,
nationality:"China",
run:function () {
console.log('Lily is running');
}
};

在对象p1中,用{}包裹一个对象,大括号中使用逗号分隔每组属性:属性值。

  • 关于属性名
  1. 用字面量来创建对象的时候,对象中的属性名可以用单引号或双引号来包裹,也可以忽略引号;
  2. 当property中出现空格、斜杠等特殊字符,或者与JS关键词冲突时,则必须使用引号;
  3. 若属性名包含了空格、-(横杠)等,属性访问方式只能采用’[ ]'中括号访问,而不能用对象.属性名的方式;
  • 关于属性值:属性的值可以是基本类型,也可以是引用类型,当属性值是一个函数的时候,我们可以称之为方法。对应的属性称之为方法名。
  • 分隔多个属性:在一个属性定义之后用逗号分隔,最后一个属性不需要。

2、使用new操作符后跟Object构造函数

var obj = new Object();
Object构造函数

这里Object是构造函数,之前我们说了构造函数也是对象也是所谓的类,Object是所有JavaScript对象的基类。
instanceof运算符可以在继承关系中用来判断一个实例是否属于它的父类型,下面的代码可以看出所谓的基类是什么意思,我们可以理解为Object对象是Javascript对象的共同祖先。

console.log('123' instanceof Object);  //false
console.log(1 instanceof Object);      //false
console.log(null instanceof Object);   //false

console.log([1] instanceof Object);  //true
console.log({} instanceof Object);   //true

var Spanner= function (material) {
this.material= material;
}
var s1 = new Spanner("Fe");
console.log(s1 instanceof Spanner);   //true
console.log(s1 instanceof Object);    //true
console.log(Spanner instanceof Object);  //true

现在用此方法创建一个对象,实际上发生了什么?

var o1=new Object();

和所有的构造函数一样,js解释器做了这些

var o1= {};   //1 首先创建一个新的临时对象
o1._proto_ = Object.prototype;      //2 引用构造函数的原型对象
Object.call(o1);      //在新对象o1的作用域中执行构造函数Object,也就是将o1赋给this。
创建方法
//使用Object构造函数创建一个对象
var p1 = new Object();
p1.trueName="Lily";
p1.age=18;

//使用字面量创建一个对象
var p2= {
"trueName": "Lily",
'age': 18
}

实际上,不推荐这个方法来创建一个对象,因为这个方法与前面的字面量方式创建对象效果基本等价,而字面量方式代码更简洁,更因为字面量方式不会调用构造函数本身,效率更高。

PS:在控制台中我们观察到p1和p2看起来是一模一样的,但是除了他们都来自己共同的祖先Object这个共同点之外,没什么特别的联系。
我们知道客观世界中的事物有着广泛的联系,在javascript世界中,对象之间也有着联系,为对象建立联系,共用属性和方法来解决问题是面向对象编程的重要工作内容。

为了减少代码的冗余,以及让对象之间产生更合理的关系,可以使用下面的方法来创建对象。

3、工厂模式

工厂模式更像是方法2的变形,解决了代码冗余的问题

//工厂模式
var person=function (name,age) {
var o=new Object();
o.name=name;
o.age=age;
return o;
}
var p1=person('Lily',18);  //{name: "Lily", age: 18}
var p2=person('Mary',20);  //{name: "Mary", age: 20}
console.log(p1 instanceof person);   //false

通过执行函数person返回结构相似对象,但是客观上对象之间没有联系。

4、构造函数

构造函数前面已经详细讲解过了,是创建对象的推荐方法之一。

//构造函数
var Person=function (name,age) {
this.name=name;
this.age=age;
}
var p1=new Person('Lily',18);   //Person {name: "Lily", age: 18}
var p2=new Person('Mary',20);   //Person {name: "Mary", age: 20}
console.log(p1 instanceof Person);  //true

在这个例子中,我们看到不但减少了冗余代码,而且现在p1和p2一样是属于Person对象的实例对象,如果我们给构造函数Person定义原型对象,那么p1和p2就能继承这些原型,使用共同的属性和方法。

5、原型模式

任何一个函数,作为对象都包含一个属性prototype,通过重写构造函数的prototype属性,客观上就实现了属性的继承。

//原型模式
var Person=function(){};
//重写原型的一种方法
Person.prototype.name='Lily';
Person.prototype.age='18';
//另一种写法
Person.prototype={
constructor:Person,
name:'Lily',
age:18
}
var p1=new Person();

在第二种方法中,因为完全重写了prototype属性,需要手动添加prototype的constructor属性,这样做有个坏处,constructor属性成为可枚举属性,通过for/in语句能够遍历到constructor。

6、组合使用构造函数模式和原型模式(推荐)

在创建对象时推荐使用构造函数和原型模式

var Person=function (name,age) {
this.name=name;
this.age=age;
}
Person.prototype.species='human';
var p1=new Person('Lily',18);
var p2=new Person('Mary',20);
console.log(p1.species);
console.log(p2.species);

p1和p2现在有了一个共同的属性即她们的物种都是人类。

7、动态原型模式

上面的方式6是常用的创建对象的方法,如果你有其他面向对象语言的编程经验,也许感觉怪怪的,如果把构造函数看做类,它的封装看起来不伦不类,如上例中,定义了一个构造函数之后,再去改写构造函数的原型,怎么看都不像一个整体,使用动态原型模式令构造函数看起来更像一个整体;从外观上看,动态原型模式对原型的改写被包含在构造函数中了。实际上这种方式是在构造函数第一次实例化的时候对原型进行改写。

//构造函数模式+原型模式
var Spanner= function (material) {
this.material= material;
}
Spanner.prototype.operation=function(){
console.log('扭螺丝');
}
var s1=new Spanner('Fe');
var s2=new Spanner('Cu');

//动态原型模式
var Spanner=function (material) {
this.material=material;
if(typeof this.operation!="function"){
Spanner.prototype.operation=function () {
console.log('扭螺丝');
}
};
}
var s1=new Spanner('Fe');
var s2=new Spanner('Cu');

8、寄生构造函数模式

这种模式的基本思想就是创建一个函数,该函数的作用仅仅是封装创建对象的代码,然后再返回新建的对象。这个模式,除了使用new操作符并把使用的包装函数叫做构造函数之外,和工厂模式几乎一样。

//工厂模式
var person=function (name,age) {
var o=new Object();
o.name=name;
o.age=age;
o.sayName = function() {
console.log(this.name)
}
return o;
}
var p1=person('Lily',18);  //{name: "Lily", job: 18, sayName: ƒ}
console.log(p1 instanceof person);   //false

//寄生构造函数模式
function Person(name, age) {
var o = new Object()
o.name = name;
o.age= age;
o.sayName = function() {
console.log(this.name)
}
return o
}
var p1 = new Person('Lily', 18);   //{name: "Lily", job: 18, sayName: ƒ}
console.log(p1 instanceof Person);   //false

9、稳妥构造函数模式

和工厂模式、寄生构造函数模式一样,稳妥构造函数模式创建出来的对象与构造函数之间没有什么关系,instanceof操作符对他们没有意义。
稳妥构造函数模式与寄生模式写法类似,但有两点不同:一是创建对象的实例方法不引用this,而是不使用new操作符调用构造函数。

//稳妥构造函数模式
function Person(name, job) {
var o = new Object()
o.name = name;
o.job = job;
o.sayName = function() {
console.log(o.name)
}
return o
}
var p1 = Person('Lily', 18);   //{name: "Lily", job: 18, sayName: ƒ}
console.log(p1 instanceof Person);   //false
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: