论坛首页 Web前端技术论坛

javascript进阶之对象篇

浏览 43489 次
该帖已经被评为精华帖
作者 正文
   发表时间:2006-04-12  
1、什么才算javascript中的对象。
   a、基本数据类型的包装对象。例如String Number Boolean.关于这三个包装对象这里不准备讨论。建议直接用var s=""; var i=1; var b=false;定义,包装类与java中的包装类不同。javascript中不要用包装类。
   b、javascript预定义的对象。Function Array Date   RegExp  Error等对象。这些对象使用比较简单,也不讨论了。
   c、用new Object()创建的对象。等同与var o={a:0,b:'s'};
   d、用自定义的构造函数创建的对象。function O(){};  var o=new O();
   e、dom模型定义的构造函数,浏览器为你创建的对象。用var o=document.getElementById();或其他方法获得。
   f、null也是对象。typeof(null)= object.undefined我理解为变量预编译的初始化值,而null是特殊的对象。如果一个变量=null,说明这个变量是个对象,但不是我上面提到的任何来源方式的对象。 如document.getElementById(页面中不存在的id);可以产生一个null对象。

   用typeof()  方法返回的是 object 的变量都是对象。 Function除外用new定义的不一定都是对象。
   发表时间:2006-04-12  
 < SCRIPT LANGUAGE = " JavaScript " > 
 <!-- 
 Object.prototype.toString = function ();  { return  'myToString'} ;
 var  o = new  Object();;
o.name = 'zkj';
o.age = 25 ;
o.desc = function ();  { return  '姓名:' + this .name + ',年龄:' + this .age} ;
 for ( var  key  in  o);  {
    alert(key + ':' + o[key] + ' type:' + typeof (o[key]););
  if ( typeof (o[key]); == ' function ');  {
        alert('执行方法key:' + (o[key]);(););
 } 
} 
alert(o);;
alert( new  Date(););;
 // --> 
 </ SCRIPT >     





 < SCRIPT LANGUAGE = " JavaScript " > 
 <!-- 
 Object.prototype.toString = function ();  { return  'myToString'} ;
 function  person();  {

} 
 var  o = new  person();;
o.name = 'zkj';
o.age = 25 ;
o.desc = function ();  { return  '姓名:' + this .name + ',年龄:' + this .age} ;
 for ( var  key  in  o);  {
    alert(key + ':' + o[key] + ' type:' + typeof (o[key]););
  if ( typeof (o[key]); == ' function ');  {
        alert('执行方法key:' + (o[key]);(););
 } 
} 
alert(o);;
alert( new  Date(););;
 // --> 
 </ SCRIPT > 



看以上两段代码,估计很多人对后面的代码熟悉,也这样写了。可他们执行结果是一样的。如果你改变了javascript对象的原型对象后会有些区别。
在这我想提出以下几个问题:
    a、javascript对象也是单根继承的对象.但不是所有对象都继承自Object.如例子中的Date对象。
    b、千万别乱定义Object.prototype原型对象。prototype.js中加了个extends被人说了半天。但我们自己写类库时,千万别尝试改Object的prototype。
    c、别用javacript语言模仿java来写代码。想上面的,需要一个person的“类”,并不是非需要定义一个,注意javascript对象的属性是可以随意增加或删除的。并不象java那样在类中写死。
    d、就上面两段代码有什么区别呢?可以简单的说是person继承了Object”类“。javascript中对象的继承是用prototype来实现的,后面我们讨论prototype原型对象。
    e、那我们应用的时候到底是否该自己定义自己的构造函数(如person),还是直接使用Object呢?这是个复杂的问题,我个人来说喜欢多用Object.
1 请登录后投票
   发表时间:2006-04-12  
开始之前我先明确个问题。如下代码


 < SCRIPT LANGUAGE = " JavaScript " > 
 <!-- 
Person.type = " person " ;
Person.writeType = function ();  {
    document.writeln( this .type);;
} 
 // var Person = function();{}//如果这样定义会报错,可以看看前面文章,函数的预编译。 
  function  Person();  {} 
Person.writeType();;
alert( typeof (Person););;
 for ( var  key  in  Person);  {
    alert(key);;
} 
 var  person = new  Person();;
 // --> 
 </ SCRIPT > 




在这里Person是个函数,但我们还可以定义它的属性(type)。而Person有Object实例的特性(for in、可以定义属性),但Person不是Object的实例。
见如下代码:

 < SCRIPT LANGUAGE = " JavaScript " > 
 <!-- 
 Object.prototype.toString = function ();  { return  'myToString'} ;
 function  Person();  {

} 
 Person.prototype.toString = function ();  { return  'Person'} ;

 var  o = new  Person();;
alert(o);;
alert(Person);
Person.toString = function ();  { return  'Person toString'} ;
alert(Person);
 // --> 
 </ SCRIPT > 




我理解function返回的数据类型是和Object同等级的数据类型。它有Object实例(new Object())的一些特性,但它不是Object的实例,因为它没有继承Object.prototype.toString=function(){return 'myToString'};但我们Person.toString=function(){return 'Person toString'};改变了覆盖了方法。
在《javascript权威指南》中,作者用这个特性实现了“类方法、类变量”static方法,与java中不同,这些方法不能用new Person()来调用。

Object              function          同等级 function可以定义属性,可以(for in)

new Object()        new function()    同等级 new function()继承Object的prototype,也会继承function的prototype


小例子。看了原型对象就很清楚了啊。 原型对象最好在代码最前面定义,很容易被覆盖啊!


 < SCRIPT LANGUAGE = " JavaScript " > 
 <!-- 
  var  Person = function  ();  {
     this .name = 'Person的构造函数中属性name';
     this .getName = function ();  {
          return   this .name;
 } 
  // this.toString=function();{}  //你把注释去掉看看效果 
 } 
Person.name = " Person " ;
Person.toString = function ();  { return   this .name + '的类方法'} ; // 我可以用this啊 
 alert(Person.toString();); // 类方法 
 var  o = new  Person();;
alert(o.getName(););; // 构造函数中的方法 
 alert(o);; // 访问toString方法   先找  对象中 构造函数中   Person的prototype中       Object的prototype中 
  Object.prototype.toString = function ();  { return  'Object的prototype中的toString'} ;
alert(o);; // Object的prototype中 
  Person.prototype.toString = function ();  { return  'Person的prototpe中的toString'} ;
alert(o);;
o.toString = function ();  { return  '我覆盖了toString方法了啊'} 
alert(o);;
alert('我不能访问前面的toString了。如果有super就好了!');;
 // 其实还是可以访问到被覆盖的原型的。那样太复杂了。 
// --> 
 </ SCRIPT > 
0 请登录后投票
   发表时间:2006-04-12  
原型对象prototype是Object或与之同等级的对象如(function,Number)的一个属性,protorype是个对象。typeof的值是object。

如果看了上一小节的最后一个例子,对自定义的“类”应该比较熟悉了。
在javascript中,可以说没有方法,因为函数和字符串一样也是种数据类型,但类中的函数可以用this关键字。下面我说的类的属性可以是方法,也可以指字段。
在一个自定义“类”中有中有几个地方可以定义属性。
   a、函数名中直接定义。  如Person.name。在这定义相当于类名的属性。静态的,访问的时候必须用Person.name来访问,不能用new Person().name访问,也访问不到。
   b、构造函数的this.中。当你用new function()时,这些属性就是你所持对象的属性。用new Person().属性  来访问。
   c、构建好对象以后,给对象增加属性。和构造函数中的属性使用类似。
   d、函数名的prototype中
   e、父类或Object 的prototype中。

(1)对象属性优先级
通过运行以下代码,我们访问对象属性优先级如下:c>b>d>e
c种属性必须在定义以后访问才有效。a种属性实例访问不到。
javascrpt语言预定义的属性不能用for in 得到。如toString


< SCRIPT LANGUAGE = " JavaScript " > 
 <!-- 
 Object.prototype.toString = function ();  {} ;
Object.prototype.name = " Object " ;
Object.prototype.porotype_name = " oObject " ;
Object.prototype.parent_name = " pObject " ;

Person.prototype.name = " Person " ;
Person.prototype.porotype_name = " oPerson " ;
 function  Person();  {
     this .name = 'Person实例';
} 
 var  o = new  Person();;
 for ( var  key  in  o);  {
    alert(key + ':' + o[key]);;
} 
 // --> 
 </ SCRIPT > 




(2)prototype属性是只读的
看如下代码,你不要试图通过变量改变原型对象的属性。你也不可能改变,你只会通过c模式给对象增加一个属性。
另外原型对象是所有实例共享的。理论上也不可以改变。

< SCRIPT LANGUAGE = " JavaScript " > 
 <!-- 
Person.prototype.name = " Person " ;
 function  Person();  {
  
} 
 var  o = new  Person();;
 var  o1 = new  Person();;
alert('o.name:' + o.name + '  ' + 'o1.name:' + o1.name);;
o.name = 'zkj';
alert('o.name:' + o.name + '  ' + 'o1.name:' + o1.name);;
 // --> 
 </ SCRIPT > 
0 请登录后投票
   发表时间:2006-04-12  
我只能说javascript的继承是模拟实现的。和java,c++中是不同的。是依靠prototype实现的。
我个人从来不用javascript的“继承”,始终认为javascript实现的继承不是真正的继承。可能是受java”毒害“够深。
在javascript中,我把继承分为两类: 类继承,对象继承。
(1)、prototype.js中的继承

prototype.js中用如下代码实现继承。我认为只是个属性拷贝过程。



 
Object.extend  =   function (destination, source);   {
   for  (property  in  source);   {
    destination[property]  =  source[property];
  } 
   return  destination;
} 

//Object.prototype.extend 感觉这句话没必要,太模仿java了,想让对象实例直接继承。
    a、prototype.js中的类继承



引用
prototype.js  1.3 . 1

   
 String.prototype.extend(  {
      stripTags:  function ();   {
       return   this .replace( /< \ /? [ ^> ] +>/ gi, '');;
    } ,

    escapeHTML:  function ();   {
       var  div  =  document.createElement('div');;
       var  text  =  document.createTextNode( this );;
      div.appendChild(text);;
       return  div.innerHTML;
    } ,

    unescapeHTML:  function ();   {
       var  div  =  document.createElement('div');;
      div.innerHTML  =   this .stripTags();;
       return  div.childNodes[ 0 ].nodeValue;
    } 
    } );;



    我把这类型的继承叫做类继承,直接把你自己写的对象属性拷贝到原型对象中去。



< SCRIPT LANGUAGE = " JavaScript " > 
 <!-- 
 Object.extend  =   function (destination, source);   {
   for  (property  in  source);   {
    destination[property]  =  source[property];
  } 
   return  destination;
} 
 
  function  Man();  {
     this .name = 'zkj';
} 
Man.prototype.type = '男人';
Man.prototype.getType = function ();  {
     return   this .type;
} 
  function  Woman();  {} 
 
Object.extend(Woman.prototype,Man.prototype);;
 var  man = new  Man();;
 var  woman = new  Woman();;
alert(man.getType(););;
alert(man.name);;
alert(woman.getType(););;
alert(woman.name);;
 // --> 
 </ SCRIPT > 



看了以上代码,可能你会明白。直接拷贝类的原型对象确实可以实现某种概念上的继承。
但要注意:在继承体系中,Man的原型对象属性方法最好不要用Man的实例属性(name),因为可能Woman中并没有定义实例属性name;也最好不要用Man)原型对象属性字段(type),虽然type也被拷贝过来了,但值还是”男人“。
虽然有解决办法,但javascript没有很好的语法检查工具,你用prototype.js的类继承时小心处理。

b、prototype.js中的对象继承

引用
prototype.js 1.3.1


this.options = {
      method:       'post',
      asynchronous: true,
      parameters:   ''
    }.extend(options || {});;



这个应用比较简单,典型的对象之间属性拷贝覆盖。
总结:关于prototype.js中继承的实现,我们当成javascript对象的属性拷贝可能在应用中更好理解。建议大家仔细读读prototype.js代码可能体会更深。模仿prototype.js中extend的应用。感觉var Insertion = new Object(); 的实现比较经典。

(1)、dojo-0.2.0-ajax中的继承

    

 
引用
dojo.inherits  =   function (subclass, superclass)  {
  if ( typeof  superclass  !=  ' function ')  {
  dojo.raise( " superclass:  " + superclass + "  borken " );
}
subclass.prototype  =   new  superclass();
subclass.prototype.constructor  =  subclass;
subclass.superclass  =  superclass.prototype;
  //  DEPRICATED: super is a reserved word, use 'superclass'
  subclass['super']  =  superclass.prototype;
     }


dojo的继承实现比较正统,也是《javascript权威指南》中的实现方法。注意最后一句代码可以实现子类访问父类原型对象的方法。


< SCRIPT LANGUAGE = " JavaScript " > 
 <!-- 
 
  function  Man();  {
     this .name = 'zkj';
} 
Man.prototype.type = '男人';
Man.prototype.getType = function ();  {
     return   this .type;
} 
  function  Woman();  {} 
 
Woman.prototype  =   new  Man();;
Woman.prototype.constructor  =  Woman;
Woman.superclass  =  Man.prototype;
 //  DEPRICATED: super is a reserved word, use 'superclass' 
 Woman['super']  =  Man.prototype;
Woman.prototype.type = '女人';

 var  man = new  Man();;
 var  woman = new  Woman();;
alert(man.getType(););;
alert(man.name);;
alert(woman.getType(););;
alert(Woman.superclass.getType(););;
alert(woman.name);;

 // --> 
 </ SCRIPT > 




看看代码,混乱之极。
dojo一直没时间仔细读读代码。这部分详细讨论待续。


(3)、总结
关于javascript的继承实现,建议一般不要使用,感觉很乱,代码可读性较差。一般也没有使用必要。详细在《9、javascript对象使用指南》中讨论。
0 请登录后投票
   发表时间:2006-04-12  
javascript对象牵扯东西太多了,另开一贴。
不对的地方欢迎来拍。

6、完全模仿java的一个类
7、Object类原型对象的属性和方法
8、浏览器为你创建的javascript的对象
9、javascript对象使用指南


待续,还没完成。
写东西比编程类多了。
努力
0 请登录后投票
   发表时间:2006-04-16  
javascript所有对象都继承自Object类。以下是Object类的一些属性。原型对象

的一些属性。

1、constructor属性

从javascript1.1开始,每个对象都有这个属性,它指向用来初始化改对象的构造

函数



 <SCRIPT LANGUAGE = " JavaScript " > 
 <!-- 
  function  Person();  {} 
 var  o = new  Person();;

alert( typeof (Person.constructor););;
alert(o.constructor);;
alert(Person.constructor);;
alert(Function.constructor);;
alert(Object.constructor);

alert( new  Date();.constructor);;
alert(Date.constructor);;


 function  Man();  {

} 
Man.prototype = new  Person();;
alert(Man.constructor);;
o = new  Man();;
alert(o.constructor);
Man.prototype.constructor = Man;
alert(o.constructor);
 // --> 
 </SCRIPT > 




如以上代码,可以知道
a、constructor的类型是函数;
b、javascript内部实现了很多函数,如Object,Date都是函数由Function得到的


c、用原型对象实现的继承中,也要设置子类的constructor。如果你的程序中用

到了constructor,可能会出错。

2、toString()方法
相当于java Object类中toString方法。你alert()  + 等操作中就会调用这个方

法。 var s='1'+'2',会自动把'1'  '2'  转化成String对象在执行。

但数组定义自己的toString方法。alert(Array.prototype.toString)

如果对象或子类要调用父类的方法可以



 <SCRIPT LANGUAGE = " JavaScript " > 
 <!-- 
alert([ 1 , 2 , 3 ].toLocalString(););
alert(Object.prototype.toString.apply([ 1 , 2 , 3 ]););;
 // --> 
 </SCRIPT > 



3、toLocalString()方法

ECMAScript v3 javascript1.5中定义了这个方法。返回局部化的值。偶还不知道

什么用法。
4、valueof()

当javascript与要将一个对象转化成字符串之外的原始类型时调用它。

5、hasOwnProperty()方法

《javascript权威指南》说如果是非继承的属性返回true.但下列代码反映,它检

验对象的实例属性。对原型属性不会返回。



<SCRIPT LANGUAGE = " JavaScript " > 
 <!-- 
  function  Person(name);  {
     this .name = name;
} 
 Person.prototype.setAge = function (age);  {
     this .age = age;
} 
 Person.prototype.toString = function ();  {
     return  'name:' + this .name + ' age:' + this .age;
} 
 var  o = new  Person('zkj');;
o.setAge( 25 );;
alert(o);
alert(o.hasOwnProperty( " name " ););;
alert(o.hasOwnProperty( " age " ););;
alert(o.hasOwnProperty( " setAge " ););;
alert(o.hasOwnProperty( " toString " ););;

alert(Person.prototype.hasOwnProperty( " setAge " ););;
 // --> 
 </ SCRIPT > 




6、propertyIsEnumerable
《javascript权威指南》如果用能 for( in )枚举的属性,这个方法返回true;
以下代码说明《javascript权威指南》是错的。自己定义的原型对象属性可以枚

举,但返回false



< SCRIPT LANGUAGE = " JavaScript " > 
 <!-- 
  function  Person(name);  {
     this .name = name;
} 
 Person.prototype.setAge = function (age);  {
     this .age = age;
} 
 Person.prototype.toString = function ();  {
     return  'name:' + this .name + ' age:' + this .age;
} 
 var  o = new  Person('zkj');;
o.setAge( 25 );;
alert(o.propertyIsEnumerable('setAge'););;
 var  desc = '';
 for ( var  key  in  o);  {
    desc += key + '  ';
     if (o.hasOwnProperty(key););  {
        desc += ' 是实例对象 ';
 } else  {
        desc += ' 不是实例对象 ';
 } 
   if (o.propertyIsEnumerable(key););  {
        desc += ' 能被枚举 ';
 } else  {
        desc += ' 不能被枚举 ';
 } 
 
 desc += '\r\n';
} 
alert(desc);;

 // --> 
 </ SCRIPT > 




7、isPrototypeOf方法

《javascript权威指南》如果调用对象是实际参数指定的对象的原型对象返回

true. 看代码吧。
居然alert(Object.prototype.isPrototypeOf(Person));//true也是true.搞不懂




 <SCRIPT LANGUAGE = " JavaScript " > 
 <!-- 
  function  Person(name);  {
     this .name = name;
} 
 Person.prototype.setAge = function (age);  {
     this .age = age;
} 
 Person.prototype.toString = function ();  {
     return  'name:' + this .name + ' age:' + this .age;
} 
 var  o = new  Person('zkj');;
o.setAge( 25 );;
alert(Person.prototype.isPrototypeOf(o););; // true 
 alert(Person.isPrototypeOf(o););; // false 
 alert(o.isPrototypeOf(Person.prototype););; // false 
 alert(Function.prototype.isPrototypeOf(Person););; // true 
 alert(Object.prototype.isPrototypeOf(Person););; // true 
// --> 
 </SCRIPT > 




8、总结

看《javascript权威指南》前,就知道toString方法。现在知道了些其他的方法

,但让我更加混乱,《javascript权威指南》讲的也有错误。开发中建议大家除

了toString,其他属性方法不要覆盖也不要使用了。除了对这些方法十分清楚。就

我知道的javascript开源框架中好象没用到这些。
0 请登录后投票
   发表时间:2006-04-16  
先加入精华,再细细看
0 请登录后投票
   发表时间:2006-04-22  
其实到了最后,你会发现javascript可以完全模拟java的语法(Java2Script技术,可以参考http://j2s.sourceforge.net/j2sclazz/),而用java可以解释运行javascript(Mozilla  Rhino http://www.mozilla.org/rhino/)则是众所周知的。

也就是说javascript和java或者c++其实是一个计算机面向对象系统的不同正交基,互相是能够实现转换的。至于如何基与基之间实现转换,就要熟悉不同基的特性,进而实现一一映射。
0 请登录后投票
   发表时间:2006-04-22  
jossonsmith 写道
其实到了最后,你会发现javascript可以完全模拟java的语法(Java2Script技术,可以参考http://j2s.sourceforge.net/j2sclazz/),而用java可以解释运行javascript(Mozilla  Rhino http://www.mozilla.org/rhino/)则是众所周知的。

也就是说javascript和java或者c++其实是一个计算机面向对象系统的不同正交基,互相是能够实现转换的。至于如何基与基之间实现转换,就要熟悉不同基的特性,进而实现一一映射。

别把javascript弄复杂了.
能模拟了又怎么样了.java的代码优雅吗?
看看ruby吧.
0 请登录后投票
论坛首页 Web前端技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics