1.对象的创建(javaScript几乎所有都是对象)
创建一个Object(Object是javaScript中所有对象的基类,所有的对象都继承Object)
var bingo = new Object();
这时变量 bingo 指向一个Object的实例,你可以为该对象动态的添加属性和函数,如下:
var bingo = new Object();
bingo.say = 'hello';
bingo.do = function()
{
alert(this.say);
}
a.javaScript对象数组
javaScript是把对象当作关联数组,也可以用数组的形式来调用 属性和方法,如下:
属性:var theFirstName = bingo[‘say’];
方法:bingo[‘do’];
往一个对象添加方法时,你也可以添加 一个已经存在的方法;如下:
为bingo对象添加一个已经存在的方法sayLoudly();
function sayLoudly()
{
console.log(this.say);
console.log(typeof this);
}
var bingo = new Object();
bingo.say = 'hello';
bingo.sayLoudly = sayLoudly;
因为this它指向的对象会在运行时动态地计算,所以因不同对象的调用它会指向不同的对象,例如下面:
sayLoudly();
首先单单直接调用sayLoudly()的话,则相当于window.sayLoudly();此时this指向的就是window对象,
因为这里的window对象没有say属性,所以输出undefined,因为window对象也是Object,所以输出Object,如下:
undefined
object
bingo.sayLoudly();
接着用bingo.sayLoudly();,此时this指向的是bingo对象,因为这里的bingo对象已有属性say,所以输出hello,
又因为bingo是一个Object的对象,则输出Object,如下:
hello
object
b.Json形式创建对象
var bingo =
{
say:”hello”,
do: function()
{
alert(this.say);
},
sayLoudly:sayLoudly,
//对象里面嵌套对象
LastName:{
lastName:’world’,
sayName: function()
{
alert(this.lastName);
}
}
}
这里的sayLoudly:sayLoudly, javaScript会将第一个sayLoudly理解为属性,
第二个理解为一个已存在的对象的引用
调用形式如下:
bingo.LastName.sayName();
2.类的定义
在javaScript中,类就是一个函数,这个函数被当作类的 构造函数 来提供服务,如下:
function newClass()
{
alert('constructor');
this.firstName = 'frank';
this.sayName = function()
{
alert(this.firstName);
}
}
调用如下:
var nc = new newClass();
nc.sayName();
当var nc = new newClass(); 执行newClass构造函数,即会立即弹出‘construcor’;
当nc.sayName(); 执行即会立即弹出‘frank’;
这里无论创建多少个newCalss的实例,它们都含有同样的属性和方法,
new newClass();都调用相同的构造函数, 都弹出‘construcor’;
但是这种方法每新建一个newClass实例都会含有 firstName属性和 sayName()方法的一份副本,
那么每个实例都占用了更多的内存(原型prototype可以解决这问题,具体如下)
a.原型prototype
在javaScript中,所有的函数(对象)都具有prototype属性,它引用一个对象。
虽然原型对象在初始化时是空的,但是你在其中定义的任何属性都会被该构造函数创建的所有对象所继承,
这也是javaScript继承的实现原理
function newClass()
{
this.firstName = 'frank';
}
newCalss.prototype.sayName = function()
{
alert(this.firstName);
}
var nc1 = new newClass();
nc1.sayName();
var nc2 = new newClass();
nc2.sayName();
现在,无论你创建了多少个newClass实例,在内存中sayName()函数都只会有一个单独的实例,
因为this是在运行时动态被计算,所以当调用nc1.sayName();时,this指向的是nc1,当调用nc2.sayName(); this指向的是nc2.
prototype(原型)有两个规则:
1. 使用原型可以大量减少每个对象对内存的需求量,因为对象可以继承许多属性。
2. 即使属性在对象被创建之后才被添加至原型中,对象也能够继承这些属性。
具体如下:
function MyObject()
{
}
MyObject.prototype.color = "red";
var obj1 = new MyObject();
console.log(obj1.color); //a
console.log(obj1.soundEffect); //a
MyObject.prototype.color = "blue";
MyObject.prototype.soundEffect = "boOOoing";
var obj2 = new MyObject();
console.log(obj1.color); //b
console.log(obj1.soundEffect); //b
console.log(obj2.color); //b
console.log(obj2.soundEffect); //b
输出如下:
red
undefined
blue
boOOoing
blue
boOOoing
首先a中输出的obj1.color为red,而因为obj1.soundEffect还未定义,不存在,所以输出为undefined;
而b中输出的obj1.color为blue,是因为在之前执行了MyObject.prototype.color = "blue";将原型中的color修改为了
blue,所以输出的obj1.color才变为blue;
b中输出的obj1.soundEffect为boOOoing,是因为在之前执行了MyObject.prototype.soundEffect = "boOOoing";
为原型添加了soundEffect 属性,所以这时输出的obj1.soundEffect才变为boOOoing(注意原来输出的是undefined)
prototype的能力不是往对象上添加属性或方法等,而是在prototype属性上添加属性和方法等,然后可以通过
对象 来访问 到其prototype上的属性或方法等,具体如下:
function MyObject()
{
}
MyObject.prototype.x = 1;
var obj = new MyObject();
alert("obj.x="+obj.x);
这里我们没有给obj添加属性x,但是依然可以得到obj.x = 1;这是因为javaScript在对象obj上找不到属性x,
它便会到生成obj对象的构造函数MyObject的prototype属性中去找,于是,找到x=1。
所以这里obj.x输出的不是obj对象上的属性,而是通过obj对象输出了prototype上的属性x
而当obj对象上也存在x属性时,obj.x先找到了obj对象的属性x了,所以它就不去生成obj对象的构造函数MyObject的prototype属性中去找
具体如下:
function MyObject()
{
}
MyObject.prototype.x = 1;
var obj = new MyObject();
alert("obj.x="+obj.x); //a
obj.x = 4;
alert("obj.x="+obj.x); //b
上面a输出的obj.x还是prototype上的属性x的值1,而b输出的obj.x因为执行了obj.x = 4,所以它找到了obj对象上的属性x,所以输出为4.
想到修改prototype,不能通过对象obj来直接修改,要通过prototype来修改,具体如下:
function MyObject()
{
}
MyObject.prototype.x = 1;
var obj = new MyObject();
obj.x = 2;
alert(MyObject.prototype.x); //a 弹出 1
MyObject.prototype.x = 3;
alert(obj.x); //b 弹出2
delete obj.x;
alert(obj.x) //c 弹出3;
输出的MyObject.prototype.x值是1,尽管再者之前执行了obj.x = 2,但这并不改变MyObject.prototype.x的值,而它是为obj这对象上添加了属性x,并将它赋值为2.所以b中输出的obj.x是2,因为它先找到了obj这对象上的属性x,就输出了这x的值,而最后c输出的obj.x为3主要是因为在这之前执行了delete obj.x,这将删除了obj对象上的属性x,所以javaScript在obj对象上找不到属性x,它就区生成obj对象的构造函数MyObject的prototype属性中去找,找到后并输出了MyObject.prototype.x的值3.
function MyObject1()
{
}
MyObject1.prototype.x = 1;
function MyObject2()
{
}
MyObject2.prototype = new MyObject1();
var obj = new MyObject2();
alert(obj.x);
输出obj.x的值为1;在这里MyObject2.prototype 被赋值为MyObject1的一个实例,所以obj.x找到的其实是
(a)MyObject2.prototype.x,而又因为(b)MyObject2.prototype = new MyObject1();所以将(b)代入(a)
可得(a)为 new MyObject1().x,而在new MyObject1()对象上找不到属性x,所以它就去生成new MyObject1()
对象的构造函数的prototype上去找,找到的其实就是MyObject1.prototype.x ,所以输出为1.