对象与数组
JavaScript中的对象本质上是一个关联数组,或者说更像java里的?Map数据结构,由key-value组成。如下:
<script> function Person(name , age) { //将name、age形参的值分别赋给name、age实例属性。 this.name = name; this.age = age; this.info = function() { alert('info method!'); } } var p = new Person('yeeku' , 30); for (propName in p) { //遍历Person对象的属性 document.writeln('p对象的' + propName + "属性值为:" + p[propName] + "<br />"); } </script>
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
JavaScript对象都都基于相同基类(Object)的实例,因此所有的JavaScript对象之间没有明显的继承关系,而且JavaScript是一种动态语言,它允许自由地为对象增加属性和方法,当程序为对象的某个不存在的属性赋值时,即可认为是为该
对象增加属性。例如:
var p={};
p.age=30;
p.info=function(){
alert("info menthod");
}
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
关于prototype
<script> //创建Person函数 function Person(name , age) { this.name = name; this.age = age; //为Person对象指定info方法 this.info = function() { //输出Person实例的name和age属性 document.writeln("姓名:" + this.name); document.writeln("年龄:" + this.age); } } //创建Person实例p1 var p1 = new Person('yeeku' , 29); //执行p1的info方法 p1.info(); document.writeln("<hr />"); //创建Person实例p2 var p2 = new Person('wawa' , 20); //执行p2的info方法 p2.info(); </script>
上述代码定义了Person函数的同时,也定义了一个Person类,而且该函数就是该Person类的构造器。
但上面为Person对象增加info方法相当不好,有两点原因:
1,
性能低下:每次创建实例都会创建info()函数,会造成内存泄漏,引起性能下降,实际上info()方法一个就好了
2,
使得info()函数中的局部变量产生闭包:闭包会扩大局部变量的作用域,使得局部变量一直存活到函数之外的的地方。例如:
<script> //创建Person函数 function Person() { //locVal是个局部变量,原本应该该函数结束后立即失效 var locVal = '疯狂Java联盟'; this.info = function() { //此处会形成闭包 document.writeln("locVal的值为:" + locVal); return locVal; } } var p = new Person(); //调用p对象的info()方法 var val = p.info(); //输出val返回值,该返回值就是局部变量locVal。 alert(val); </script>
为了避免这两种情况,通常不在函数定义(也就是类定义)中直接为该函数定义方法,而是使用prototype属性。JavaScript所有的类(也就是函数)都有一个prototype属性,在为JavaScript类的prototype属性增加函数,属性时,即可视为对原有的
类的扩展。
我们可以理解为增加了prototype属性的类继承了原有的类——这就是JavaScript所提供的伪继承机制。
如下:
<script> //定义一个Person函数,同时也定义了Person类 function Person(name , age) { //将局部变量name、age赋值给实例属性name、age this.name = name; this.age = age; //使用内嵌的函数定义了Person类的方法 this.info = function() { document.writeln("姓名:" + this.name + "<br />"); document.writeln("年龄:" + this.age + "<br />"); } } //创建Person的实例p1 var p1 = new Person('yeeku' , 29); //执行Person的info方法 p1.info(); //此处不可调用walk方法,变量p还没有walk方法 //将walk方法增加到Person的prototype属性上 Person.prototype.walk = function() { document.writeln(this.name + '正在慢慢溜达...<br />'); } document.writeln('<hr />'); //创建Person的实例p2 var p2 = new Person('leegang' , 30); //执行p2的info方法 p2.info(); document.writeln('<hr />'); //执行p2的walk方法 p2.walk(); //此时p1也具有了walk方法——JavaScript允许为类动态增加方法和属性 //执行p1的walk方法 p1.walk(); </script>
伪继承实质上是修改了原来的类,而不是产生一个新的之类,所以原来没有walk()方法的Person类将不存在了。
上面的程序也说明了JavaScript是一门动态语言,不仅可以为
对象动态增加属性和方法,还可以为
类动态增加属性和方法!
还可以通过使用prototype属性,可以对JavaScript的内建类进行扩展。如下:
<script> //为Array增加indexof方法,将该函数增加到prototype属性上 Array.prototype.indexof = function(obj) { //定义result的值为-1 var result = -1; //遍历数组的每个元素 for (var i = 0 ; i < this.length ; i ++) { //当数组的第i个元素值等于obj时 if (this[i] == obj) { //将result的值赋为i,并结束循环。 result = i; break; } } //返回元素所在的位置。 return result; } var arr = [4, 5, 7, -2]; //测试为arr新增的indexof方法 alert(arr.indexof(-2)); </script>
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
与传统面向对象程序设计语言不同的是,JavaScript中的函数永远是独立的,函数永远是一等功民,函数永远不会从属于其他类,对象。即使这个还个函数是匿名内嵌函数。如下:
<script> //定义Dog函数,等同于定义了Dog类 function Dog(name , age , bark) { //将name、age、bark形参赋值给name、age、bark实例属性 this.name = name; this.age = age; this.bark = bark; //使用内嵌函数为Dog实例定义方法 this.info = function() { return this.name + "的年纪为:" + this.age + ",它的叫声:" + this.bark; } } //创建Dog的实例 var dog = new Dog("旺财" , 3 , '汪汪,汪汪...'); //创建Cat函数,对应Cat类 function Cat(name,age) { this.name = name; this.age = age; } //创建Cat实例。 var cat = new Cat("kitty" , 2); //将dog实例的info方法分离出来 var tmp = dog.info; //通过function的call方法完成cat的调用info方法 alert(tmp.call(cat)); </script>
JavaScript中的方法调用有两种方式:
1,正常方法 obj.method(args...)
2,方法回调 method.call(obj,args...)
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
JavaScript建对象
大致三种方法:
使用关键字new创建对象
<script> //定义一个函数,同时也定义了一个Person类 function Person(name , age) { //将name、age形参赋值给name、age实例属性 this.name = name; this.age = age; } //分别以两种方式创建Person实例 var p1 = new Person(); var p2 = new Person('yeeku' , 29); //输出p1的属性 document.writeln("p1的属性如下:" + p1.name + p1.age + "<br />"); //输出p2的属性 document.writeln("p2的属性如下:" + p2.name + p2.age); </script>
使用Object创建即时对象
<script>
var myObj = new Object();
myObj.info = new Function("document.writeln('对象的name属性:' + this.name);"
+ "document.writeln('<br />');"
+ "document.writeln('对象的age属性:' + this.age)");
document.writeln("<hr / >");
myObj.name = 'yeeku';
myObj.age = 29;
//为对象增加方法
myObj.info();
</script>
<script>
//创建空对象
var myObj = new Object();
//为空对象增加属性
myObj.name = 'yeeku';
myObj.age = 29;
//创建一个函数
function abc()
{
document.writeln("对象的name属性:" + this.name);
document.writeln("<br />");
document.writeln("对象的age属性:" + this.age);
};
//将已有的函数添加为对象的方法
myObj.info = abc;
document.writeln("<hr>");
//调用方法
myObj.info();
</script>
使用JSON语言创建对象
<script> //代码 var person = { //定义第一个简单属性 name : 'wawa', //定义第二个简单属性 age : 29 , //定义第三个属性:数组 schools : ['小学' , '中学' , "大学"], //定义第四个属性,对象数组 parents :[ { name : 'father', age : 60, address : '广州' } , { name : 'mother', age : 58, address : '深圳' } ], //定义方法 info:function(){ alert("hello world"); } }; alert(person.parents[0].name); </script>