Javascript面向对象-创建对象

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

猜你喜欢

转载自blog.csdn.net/dreamingbaobei3/article/details/89360843