对象的创建
创建对象
Js中:
- 一切都是对象
- 对象是属性的集合
- 对象是由函数创建的
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值。