zoukankan      html  css  js  c++  java
  • 【JavaScript】变量定义提升、this指针指向、运算符优先级、原型、继承、全局变量污染、对象属性及原型属性优先级

    参考资料http://caibaojian.com/toutiao/5446

    1、所有变量声明(var)或者声明函数都会被提升到当前函数顶部

       关于函数表达式,js会将代码拆分为两行代码分别执行。这里需要注意的是

    var getName 和 function getName都是声明语句,区别在于var getName是函数表达式,function getName是函数声明,这里使用var进行函数声明和变量声明时一样的,都是声明提前至当前函数最顶部,二函数声明是将函数声明提升至当前函数顶部。(这个有点绕,但是可以看到本质就是声明提前,function getName整个是函数声明,声明提前,而var getName后接的是函数表达式,和声明变量一样,声明提前,赋值留在原地。)

      (实名函数和匿名函数,这个说法可能会更熟悉一些,

        实名函数:不论声明在哪里都会在其他代码执行前,被提升到当前作用域最顶端以准备被调用;

        匿名函数:(函数的表达式的表达形式)实际上是个变量,在声明之前无法被调用。)

    console.log(x);
    var x = 1;
    function x(){};

    这三行简单的代码,var x = 1;将被拆分为var x;x=1;两个部分,声明提前至当前函数顶部,赋值留在原地,而函数表达式也会提升至当前函数最上方。

    var x;
    function x(){};
    console.log(x);
    x=1;

    实际运行过程中函数如上顺序执行,因此输出x为function(){}。

      当没有进行var声明的时候,需要在当前函数作用域寻找是否存在该变量声明,如果没有,则向上一层继续寻找,注意,如果此处依然没有,那么会向上寻找直至window对象,若window对象中也没有该属性,那么就会在window中创建该变量。

    2、this指向是由所在函数的调用方式来决定的。

    3、关于构造函数

      构造函数不能直接被调用,必须通过new运算符在创建对象时才会自动调用,一般当函数执行到的时候自动调用。

    4、this在构造函数中代表当前实例化对象。

    题目

    function Foo(){
        getName = function(){alert(1);};
    }
    Foo.getName = function(){alert(2);};
    Foo.prototype.getName = function(){alert(3);};
    var getName = function(){alert(4);};
    function getName(){alert(5);};
    
    (1)Foo.getName();
    (2)getName();
    (3)Foo().getName();
    (4)getName();
    (5)new Foo.getName();
    (6)new Foo().getName();
    (7)new new Foo().getName();

    在理解了上面的话以后前四题应该是非常简单的,归根结底一句话,变量声明和声明函数提前至当前函数顶部。

    (1),直接调用Foo.getName(),输出2;

    (2),getName(),函数顺序执行,这里我们看到var getName和function getName函数表达式即将var getName 提至顶部,下面将函数声明提前,那么是先运行的function getName(){alert(5);};后执行getName = function(){aleert(4);};后面将前面覆盖了,输出4。

    (3),显然先调用Foo函数,第一个调用以后,这里运行了getName = function(){alert(1)}这是一个函数表达式,我们先看当前函数内部是否存在变量声明,并没有那么找到外面,var getName = function(){alert(4);};这里就覆盖了这个函数表达式,进行新的赋值。此处return this,即执行this.getName(),此处直接调用,那么this指向window。输出1.

    (4),经过上一步运行,getName()被覆盖,依然输出1。

    5~7题

    主要是构造函数通过new进行实例化。

    (5),new(Foo.getName)(),将getName函数通过构造函数来执行,输出2

    这里有一个构造函数的返回值问题。

    在js构造函数中可以有返回值也可以没有,我们这样看

    function F(){};
    >undefined
    new F();
    >F {}

    如果有返回值,检查检查值是否是引用类型,如果是非引用类型,如基本类型(string、number、boolean、null、undefined)则与无返回值相同,实际返回其实例化对象。

    如果是引用类型,那么实际返回值为引用类型。

    function f(){return true;};
    >undefined
    new f();
    >f {}
    function f(){return {1:"a"}};
    >undefined
    new f();
    >Object {1: "a"}

    此处返回值为this,this在构造函数中表示当前实例化对象,因此返回当前实例化对象。因为在Foo构造函数中没有为构造函数添加任何属性,因此到当前对象的原型对象(prototype)中寻找getName,找到了。

    (6)(7)输出3.

  • 相关阅读:
    Android Studio 打包生成apk
    找水王
    关于搜狗输入法的用户体验评价
    c语言函数的嵌套使用和矩阵运算
    人月神话阅读笔记02
    第一阶段冲刺意见评论汇总
    高校表白App-团队冲刺第十天
    高校表白App-团队冲刺第九天
    高校表白App-团队冲刺第八天
    人月神话阅读笔记01
  • 原文地址:https://www.cnblogs.com/hodgson/p/6014954.html
Copyright © 2011-2022 走看看