对象的创建

创建对象

Js中:

  • 一切都是对象
  • 对象是属性的集合
  • 对象是由函数创建的

1.字面量方式(掌握)

对象的创建
注意:

  1. 在属性的值中的this不表示当前的对象.
    对象的创建
    上面的weight这个属性值,并不是130,而是NaN。
    改一下代码:
    在外面定义一个age,这个age其实就是window的一个属性,可以通过window.age去访问。
    对象的创建
    我们发现weigth的值是 120,不是130。
    原因:
    (1)你一定要知道,如何去确定this的值。当代码运行时才去确定。
    对象的创建
    它的值就不会是 30.
    (2)对象是属性的无序集合。
    对象的创建
    2.在方法中可以使用this.

对象的创建

优缺点

优点:
直接,简单
缺点
一次只能定义一个对象。
再次定义对象,只复制代码了:
它特别的适用于:只需要有一个对象的情况。

例子:矩形对象

矩形对象
属性:width,height
方法:求面积(); 求周长();对象的创建

1. 求周长();对象的创建

可以直接前面创建的对象基础上,增加新的属性。

2. 调整宽度

对象的创建

3.创建另一个矩形对象对象的创建

创建一个新对象,这个操作是比较麻烦的。

能否批量创建对象?

2.用工厂函数创建对象

对象的创建
对象就是工厂中生产的产品。
属性(和方法)就是用于生产产品材料。

现在的需求是:
创建两个矩形对象:
r1的宽高是11,12
r2的宽高是22,23

按前面的字面量的方式,则要写两遍代码:
对象的创建
对象的创建

1. 工厂函数

对象的创建

2. 优缺点

优点:可以快速地,批量创建对象。
对象的创建

缺点:
(1)方法并没有共享。

对象的创建
对象的创建
(2)你生产产品并没有”商标”
理解为:你创建的对象的构造器都是Object,没有表现当前的对象的特殊之处。

对象的创建
所有产品都是由Object创建,而并没有体现出是属于矩形这一类的。

解决办法: new

3.构造器方法 创建对象

对象的创建

1. 加new和不加new 的区别

不加new :直接调用函数Rect(),由没有明确的return,所以r1的值是undefined.
在调用Rect()时,this是指向window的,所以this.width和this.height就给window对象加了两个属性。
对象的创建
对象的创建

加new
对象的创建
加了new之后,得到是一个对象。代码中的this就相当于是返回值r2:因为加在this上的属性都发现,最后加到了r2上面。
同时:
关注r2这个对象的构造器:
对象的创建

加new到底发生了什么

对象的创建

new做了如下四件事:

  • (1) var o = {}; //在函数的内部创建一个空对象
  • (2) Rect.call(o); //调用Rect函数,同时把函数中的this用o来代替。加在this 上的属性就会加到了o上面去。
  • (3) o.proto = Rect.prototype;//构建原型链
  • (4) return o; //返回这个对象

用new去批量创建对象

对象的创建
这里的r1,r2这两个对象,它们的构造器就不像是工厂函数中一样是Object,现在它们有了自己特殊的构造器Rect。

注意:
构造器本质上就是一个普通的函数,我们一般会把它的名字首字母大写。

进一步,给它们添加求面积,求周长的功能

对象的创建
现在的问题是:
R1和r2对象 是否共用getS和getC方法呢?

Console.info( r1.getS === r2.getS);
对象的创建
目前仍然各是各个,没有共用 。

意示图:
对象的创建
与工厂函数创建的对象的结果是一样的。

原因是:r1,r2各自都有自己的属性:
对象的创建

解决上面的问题:

对象的创建
对象的创建
所以,为了让这样对象共用方法,我们可以把方法写在构造器的原型上。

优缺点

优点:
解决对象的构造器不清晰的问题;
也可以批量创建对象

缺点:
没有解决方法共用的问题。

4.构造器+ 原型 创建对象(掌握)

在构造器方式的基础上,把方法拿出来,写在构造器的原型上:对象的创建
Rect.prototype === r1.proto
写在Rect.prototype 上的属性,就相当于写在r1.__proto__上,所以r1也是可以访问。

现在再来看:r1.getS与r2的getS是否相等 :答案是 true
对象的创建
图示:对象的创建

prototype的写法有一个小细节

单个设置

我们上面的代码是单个设置的:对象的创建
这样写,每一个对象的构造器就是正常的,是Rect。
对象的创建

一起设置

也可以直接把所有的方法写在一个对象中,然后给Rect.protoype一起设置,如下:
对象的创建

构造器就会丢失,变成Object了。对象的创建
构造器丢失的原因是:你现在是整体设置了Rect.prototype,就会把它原来的所有的属性都覆盖掉。

在你没有定义Rect.prototype之前,这个对象也并不是空的。它有一个属性constuctor,而这个属性就是指向构造器的。
对象的创建
对象的创建
所以,你重新给它设置一个对象之后,就会把构造器覆盖掉了。

所以解决办法是:手动修正:
对象的创建

5.创建对象小结

  • 如果你的对象只需要创建一个:则使用字面量方式直接创建
  • 如果你的对象可能需要创建多个:构造器+原型的方式

6.补充:

1. 不加new也可以创建对象

对象的创建
上面代码,你是一定要写new才能创建对象,否则,得到的r2就是undefined.

我们可以使用一个小技巧,让用户可以加new 也可以不加new 。

对象的创建
解释:
if(!( this instanceof Rect)){ return new Rect(yourwidth,yourheight); }

Instanceof 作用是用于判断某一个对象 是不是构造器的实例 。

格式如下:
对象 instanceof 构造器
返回:true false
对象的创建
如果用户没有加new,则 this就是window,显然window instanceof Rect 是false,
在这种情况下,我们要return new Rect()

2. 关于构造器的返回值(掌握)

如果你在调用函数前加new,而这个函数又有自己的return:

(1)如果return的值是一个基本数据类型,则加 new调用,得到返回值还是一个对象,而不是以return值为准。
(2)如果return的值是一个引用数据类型,则加new调用和不加new调用,得到的值就是这个return值。对象的创建
对象的创建

对象的创建