zoukankan      html  css  js  c++  java
  • 记Javascript一道题的理解

    http://www.cnblogs.com/cqhaibin/archive/2017/05/02/6798465.html

    function Foo(){
        getName = function(){ console.log("1"); }
        return this;
    }
    Foo.getName = function(){
        console.log("2");
    }
    Foo.prototype.getName = function(){
        console.log("3");
    }
    var getName = function(){
        console.log("4");
    }
    function getName(){
        console.log("5");
    }
    Foo.getName(); //2
    getName(); //4
    Foo().getName(); //1
    getName(); //1
    new Foo.getName(); //2 => new (Foo.getName)() new无参数列表
    new Foo().getName(); // 3 => (new Foo()).getName(); //new有参数列表
    new new Foo().getName(); //3 => new ((new Foo()).getName)() //new有参数列表

    Foo.getName()

    输出结果为:2
    原理:他调用的是Foo的静态方法(如果C#、java等后端语言来说),其实是因为Javascript中的Function本身就是Function和Object的结合,所以function既是函数,也是对象。在这里Foo就是执行了他对象上的一个function而已。

    getName()

    输出结果为:4
    原理:可能你会想为什么不是5,function变量会提升到作用域的顶部,而var定义的则不会,所以var声明的覆盖掉function声明。所以结果为4

    Foo().getName()

    输出结果为:1
    原理:Foo()是函数调用,Foo执行体中对getName进行了重新赋值(全局的getName,根据作用域链向上查找),返回的this为window(Foo执行时没有调用,默认为全局),然后.getName()调用了全局的getName(也就是被Foo执行体重写的getName),所以结果为:1

    getName()

    输出结果为:1 原理:因为Foo执行体中对全局getName重写了,这时调用的又是全局的getName。所以结果为:1

    new Foo.getName()

    输出结果为:2
    原理:

    • 由于new无参,与new有参的运算优化级一样。new有参的与.运算符同一级别,而new无参的低一个级别。所以会先执行.运算符选择到Foo的静态方法getName
    • 然后执行new,获得的是Foo.getName的一个实例。所以输出结果为:2

    new Foo().getName()

    输出结果为:3

    原理:

    • 由于new是有参的,与.运算符同级,按照从左向右的执行顺序,先执行new Foo()。
    • new Foo()是需要值得我们的注意,因为他有一个返回值。存在返回值分为两种情况:
      • 无返回与返回为基本类型是一样的效果:返回都是实例对象(也就是当前的this)
      • 返回为引用类型:返回的为这个引用类型的对象,此时实例对象被替换了(也就是当前的this没有返回)。因数new Foo()返回是实例对象
    • .getName():选择是上一步实例的此方法,所以输出结果为:3

    new new Foo().getName()

    输出结果为:3
    原理:主要是运算符优先级的考查,实例开发中应该不会这样直接的用到。首先new有参,然后.getName(.运算符)(为什么是.运算符,这是因为new无参级别低一个档次),再则new有参。

    以上为链接文章中内容.

    如果我们来修改下上面函数声明foo代码如下, 结果又会如何呢?

    function Foo(){
        getName = function(){ console.log("1"); }
         
        function getName(){
            console.log('6');
        }
        return this;
    }

    执行结果:

    注意到第三和第四个输出值变为4了. 其原因是:

    Foo()方法执行时,会执行方法体中的代码.  在执行第一行变量getName的函数表达式时, 因为并没有使用var声明局部变量(事实上就算在当前情况下使用var声明结果也一样), 根据作用域链向上查找(函数声明提升的关系), 其实修改的是Foo()方法体中的函数声明getName,全局作用域中的getName并没有被修改. Foo()方法执行结束后返回this(函数调用对象,当前window). 所以执行window.getName(), 参照上面第二条输出的解释, 其结果当然就是4啦....

    传送门: 

    详解Javascript 函数声明和函数表达式的区别[因为不同浏览器js解析引擎不同,该链接文章后半部分关于if(true){....}部分不同浏览器的解析结果不一致(有的会使用前面的,有的else中的函数声明会覆盖掉前面的,请知悉)]

  • 相关阅读:
    基于C#.NET C/S架构的生产看板管理系统软件开发框架平台
    VS.NET后端框架,C#.NET开发的服务器端开发框架
    开源.NET开发架构.NET管理系统框架-原创作品
    开源.NET开发架构 .NET管理系统框架
    基于MVC架构的WebApi服务端开发框架核心优势|C/S框架网原创作品
    基于C#.NET三层架构物流运输管理系统(TMS)-C/S框架网原创作品
    C#Winform+SQL开发的基于C/S架构大型ERP系统
    MES系统框架及MES开源框架|C/S框架网软著产品
    C#.NET程序升级框架之软件版本自动升级系统
    原创C/S应用程序开发平台与.NET快速开发框架
  • 原文地址:https://www.cnblogs.com/dfyg-xiaoxiao/p/6804737.html
Copyright © 2011-2022 走看看