`
风雪涟漪
  • 浏览: 496865 次
  • 性别: Icon_minigender_1
  • 来自: 大连->北京
博客专栏
952ab666-b589-3ca9-8be6-3772bb8d36d4
搜索引擎基础(Search...
浏览量:8765
Ae468720-c1b2-3218-bad0-65e2f3d5477e
SEO策略
浏览量:17663
社区版块
存档分类
最新评论

Javascript Prototype (二)

阅读更多

穷举属性(Enumerating Properties)

要列出对象所有的属性可以用for.in循环来做

var o = {p1: 1, p2: 2};
for (var i in o) {
  console.log(i + '=' + o[i]);
}

 结果为:p1=1,p2=2

 

但是有以下几点需要注意

  • 并不能把对象的所有属性列出来。像constructor属性就没有。可以列出的属性我们叫它可以枚举的(enumerable),可以用propertyIsEnumerable()方法来判断属性是否可以列出来。
  • 可以把prototype的属性列出来,如果要判断对象的自身属性可以用hasOwnProperty() 方法
  • 虽然可以列出所有prototype的属性,但是如果使用propertyIsEnumerable()方法来校验prototype的属性,它的返回结果都是false.

让我们看个综合例子就明白了

function Gadget(name, color) {
  this.name = name;
  this.color = color;
  this.someMethod = function(){return 1;}
}
Gadget.prototype.price = 100;
Gadget.prototype.rating = 3;

 创建一个新的对象

var newtoy = new Gadget('webcam','black');
for (var prop in newtoy) { 
  console.log(prop + ' = ' + newtoy[prop]); 
}

 结果为

   name = webcam
   color = black
   someMethod = function () { return 1; }
   price = 100
   rating = 3

 如果要区分自身属性和prototype属性,那就用hasOwnProperty()方法

 

for (var prop in newtoy) { 
  if (newtoy.hasOwnProperty(prop)) {
    console.log(prop + '=' + newtoy[prop]); 
  }
}

 结果为

  name=webcam
  color=black
  someMethod=function () { return 1; }

 再来看一下propertyIsEnumerable的方法

newtoy.propertyIsEnumerable('name');//true

 大部分内置的属性和方法都是不可以列举的

newtoy.propertyIsEnumerable('constructor');//false

 任何的属性来自prototype的都不能被列举

 newtoy.propertyIsEnumerable('price');//false

 如果进入prototype内部去调用属性就可以被列举了

 newtoy.constructor.prototype.propertyIsEnumerable('price');//true

 

扩展内置对象

内置对象就是由构造函数Array,String,Object。函数可以扩展它们的prototype,也就意味着你可以通过prototype添加Array的功能。

Array.prototype.inArray = function(needle) {
  for (var i = 0, len = this.length; i < len; i++) {
    if (this[i] === needle) {
      return true;
    }
  }
  return false;
}

 现在所有的Array都有了新的方法。

var a = ['red', 'green', 'blue'];
a.inArray('red');//true
a.inArray('yellow');//false

 通过prototype扩展Array的功能真是很简单的事情。

 

关于扩展内置对象的讨论

Prototype库是个比较有名的javascript库,它通过这种方法,把javascript变成了类似ruby的语言。但是YUI却反对这种做法。如果你会使用Javascript,一般希望用javascript正常的写法,改变了核心方法,会对开发人员造成许多困惑。

现在的javascript和浏览器功能都逐渐的增多,本身开发人员对Javascript核心的扩展,很可能明天就会没什么用处了。最佳实践是先判断核心的功能是否存在,然后再去扩展。如:

if (!String.prototype.reverse) {
  String.prototype.reverse = function() {   
    return Array.prototype.reverse.apply(this.split('')).join(''); 
  } 
}

 关于prototype令人迷惑的地方

function Dog(){
    this.tail=true;
}
var benji = new Dog();
var rusty = new Dog();
Dog.prototype.say = function(){
    return 'Woof';
}
benji.say();//Woof 
rusty.say();//Woof
benji.constructor;//Dog()
rusty.constructor;//Dog()
benji.constructor.prototype.constructor;//Dog()
typeof benji.constructor.prototype.tail;//undefined

Dog.prototype={paws:4,hair:true};
//Dog.prototype.constructor = Dog;
typeof benji.paws;//undefined
alert(benji.say());//Woof

var lucy = new Dog();//new object
alert(lucy.paws);
alert(lucy.tail)

lucy.constructor;//Object();
benji.constructor;//Dog():

typeof lucy.constructor.prototype.paws;//undefined
typeof benji.constructor.prototype.paws;//number

新建一个构造函数并创建两个对象

function Dog(){
    this.tail=true;
}
var benji = new Dog();
var rusty = new Dog();

建完对象之后,我们仍然可以添加属性到prototype中,对象可以访问这个新添加的属性

Dog.prototype.say = function(){
    return 'Woof';
}
benji.say();//Woof 
rusty.say();//Woof

 让我们来看看创建对象的构造函数,一起看来很正常

benji.constructor;//Dog()
rusty.constructor;//Dog()

 看如下代码很有意思的事情发生了。。。。。

benji.constructor.prototype.constructor;//Dog()

当我们想知道prototype的构造函数是啥的时候,问题出现了。。。结果是Dog()。但是这不完全正确。prototype对象仅仅是个Object对象,他并没有任何关于Dog的属性。。。测试看看

typeof benji.constructor.prototype.tail;//undefined

让我们继续深入下去。当完全重写prototype对象时看看会怎么样。

Dog.prototype={paws:4,hair:true};

发现了以前创造的对象竟然访问不了新的prototype的属性。。。

typeof benji.paws;//undefined
benji.say();//Woof

说明了旧的对象还是指向以前的Prototype了。

让我们新建一个对象看看会怎样

var lucy = new Dog();//new object
lucy.say();//TypeError:lucy.say is not a function
lucy.paws;//4

说明新建的对象已经指向新的prototype了。

但是lucy这个对象的构造函数变成了object

lucy.constructor;//Object();
benji.constructor;//Dog():

最令人感到困扰的是prototype的属性

typeof lucy.constructor.prototype.paws;//undefined
typeof benji.constructor.prototype.paws;//number

所以如果想完全重写prototype属性,建议用以下的方式。

Dog.prototype={paws:4,hair:true};
Dog.prototype.constructor=Dog;

 这样就不会造成以上的困扰了。。。。

 

3
0
分享到:
评论
3 楼 yujintao529 2013-06-04  
   
2 楼 cwqcwqmax9 2012-12-20  
建议 楼主 看看 这片文章就明白了  http://www.iteye.com/topic/1117700

1 楼 wuwenjie0506 2010-03-24  
谢谢楼主,再firebug下面调试一下就很清楚了.

相关推荐

Global site tag (gtag.js) - Google Analytics