Javascript一些细节问题(一)

近些天由于应聘压力,看了许多书,总结一些细节问题。这些出自人民邮电的《JavaScript DOM 高级程序设计》

细节1(赋值和引用):

  1. var foo = exampleFunction();
  2. var foo = exampleFunction;

这两个虽然写法相似,但是意义却截然不同,第一行中foo的值等于exampleFunction()的计算结果,而第二行中foo是examplFunction()的引用,也算是别名。

细节2(给构造函数添加属性):

我们都知道javascript能够动态的给对象添加属性。即

  1. function test(){
  2.    //code
  3. }
  4. var obj = new test();
  5. obj.name='hor';
  6. console.log(obj.name);

如上述代码所述,在创建了obj对象之后动态的给obj对象添加属性。下面来看另外一个例子:

  1. var myConstructor = function(){
  2.    //code
  3. }
  4. myConstructor.name = 'wenlonghor';
  5. myConstructor.alertName = function(){
  6.    console.log(this.name);
  7. }
  8. myConstructor.alertName();//输出wenlonghor
  9. var obj = new myConstructor();
  10. obj.alertName()//报错

  上述代码中,我试图动态的给myConstructor添加属性和方法。但是只有第八行代码能够成功输出。本以为第十行也能顺利的输出wenlonghor。

  分析错误原因知道,原来我们定义了myConstructor。这是myConstructor既是一个实例,也是一个构造函数。动态添加成员变量只能够在实例中添加,而不能够应用到构造函数中。所以,我给myConstructor添加的name和alertName实际上是给myConstructor示例添加的。

  myConstructor是Function()的实例对象。所以就能够解释上述代码为何会报错了。因为构造函数中没有添加成功name和alertName属性。

反过来再看同样的例子,我在给他改造一下:

  1. var myConstructor =function(){
  2.    //code
  3. }
  4. myConstructor.prototype.name = 'wenlonghor';
  5. myConstructor.prototype.alertName = function(){
  6.    console.log(this.name);
  7. };
  8.  
  9. myConstructor.alertName();//报错
  10. var obj = new myConstructor();
  11. obj.alertName();//输出wenlonghor

  在上述代码中,我是用Prototype对之前的一个例子改造,这一下反过来第9行报错,而第11运行成功。

  分析错误原因得从原型链说起。在上一个例子中说到,myConstructor是Function()的实例对象。在第4-5行中给myConstructor添加Prototype属性是给构造函数myConstructor()的Prototype添加的属性。在我之前的一篇写Prototype chain中有一个图中可以清楚的看到。

  再继续解释,当调用myConstructor. alertName()的时候,会把myConstructor当做一个实例对象,因为当前myConstructor对象没有alertName属性,所以会找其构造函数的Prototype中alertName属性。而我们的属性是添加在myConstructor这个构造函数的Prototype。所以向上追溯到头找不到alertName属性,从而报错。

  反观obj.alertName();输出wenlonghor成功。根据上一段的解释我想应该明白为什么能够追溯到alertName属性了吧。因为obj是myConstructor()这个构造函数的实例,所以在obj中没有找到alertName属性会从其构造函数的Prototype中向上追溯,alertName就定义在myConstructor.Prototype中,所以匹配成功。使用一个图也许能够更清楚的解释其中的过程。

  上图中__proto__和constructor与__proto__和Prototype是为了指明这个对象是一个实例对象还是构造函数

  在obj寻找属性的过程会是图中圆圈1与圆圈2,Constructor是圆圈3与圆圈2。而属性name和方法alertName是定义在圆圈1的过程中,所以。。。

posted on 2013-10-07 14:11  wenlonghor  阅读(157)  评论(0编辑  收藏  举报

导航