• 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的过程中,所以。。。

  • 相关阅读:
    WPF自定义控件
    NPOI设置Excel单元格字体、边框、对齐、背景色
    关于StreamReader.ReadToEnd方法
    ASP.NET Core Web多语言项目
    docker与虚拟机的区别
    C# Task.Run 和 Task.Factory.StartNew 区别
    MVC的SignalR例子
    深圳游玩攻略
    一个域名下多个Vue项目
    Linq的执行效率及优化
  • 原文地址:https://www.cnblogs.com/wenlonghor/p/3355395.html
Copyright © 2020-2023  润新知