美文网首页
JavaScript2

JavaScript2

作者: Timmmmmmm | 来源:发表于2016-09-06 11:59 被阅读20次

    1. 函数声明和函数表达式有什么区别?

    函数声明 (Function Declaration):
    function functionName () {
        //statement
    }
    
    函数表达式 (Function Expression):
    var funExp = function() {
        //statement
    };
    
    区别:
    1. 函数声明以 function 开头
    2. 函数表达式要在语句后加分号,而函数声明不用(即使加了分号,也就视为空语句。)
    3. 函数声明在 JS 解析时,会进行函数提升,在同一个作用域内,不管函数声明在哪里(即使在非常靠后的位置)创建,它都会提升到作用域顶部。
    代码演示:
    printName('Tim');
    function printName(name) {
        console.log(name);
    }
    
    函数声明.png

    即使函数声明在后面,也能调用函数!--> (函数提升)

    printNameAgain('Tim');
    var printNameAgain = function(name) {
        console.log(name);
    }
    
    函数表达式.png

    报错了!!!
    因为,JS 引擎室这样处理代码的:

    var printNameAgain;
    printNameAgain('Tim');
    var printNameAgain = function(name) {
        console.log(name);
    }
    

    可见,只是将声明了函数变量,并没有赋值(相当于 undefined)。

    所以,函数表达式只把函数变量声明提前,而函数语句部分并没有提前。

    2. 什么是变量的声明前置?什么是函数的声明前置?

    变量的声明前置:变量的声明被提前到代码头部。
    console.log(a);
    var a = 1;
    
    变量声明前置.png

    可见,这并没有报错!

    因为,JS引擎解析代码时,相当于:

    var a;
    console.log(a);
    a = 1;
    
    2. 函数声明前置:将函数声明语句提前到代码头部
    printName('Tim');
    function printName(name) {
        console.log(name);
    }
    
    函数声明前置.png

    相当于:

    function printName(name) {
        console.log(name);
    }
    printName('Tim');
    

    3. arguments 是什么?

    在函数内部,你可以使用 arguments 对象获取到该函数的所有传入参数

    argu("T","i","m");
    function argu() {
        console.log(arguments[0]);
        console.log(arguments[1]);
        console.log(arguments[2]);
    }
    
    arguments.png

    4. 函数的重载怎样实现?

    在静态语言里,确定函数是靠:函数名+参数列表。

    相同名字的函数参数个数不同或者顺序不同都被认为是不同的函数,称为函数重载

    JavaScript没有函数重载这个概念,只要函数名字相同(参数不同也无所谓),就会被认为是同一个函数。

    为了实现函数重载(实现一个函数参数不同,功能相同的功能),需要利用 argument

    function sum() {
        var sum = 0;  //注意:这里需要设置 sum = 0
        for (var i=0; i<arguments.length; i++) {
            sum = sum + arguments[i];
        }
        return sum;  //如果没有 return,输出结果是 undefined
    }
    console.log(sum(1,2,3));
    

    5. 立即执行函数表达式是什么?有什么作用?

    () 将“函数声明”变为“表达式”并立即执行该表达式。

    (function() {statement}) ();
    

    或者

    (function() {statement} ());
    

    因为这是一个语句,而不是函数声明,所以不会发生“函数前置”。

    作用是,包裹一段代码,让这段代码拥有自己的作用域。

    6. 什么是函数的作用域链?

    作用域就是变量与函数的可访问范围,即作用域控制着变量与函数的可见性和生命周期。在JavaScript中,变量的作用域有全局作用域和局部作用域两种。

    例子:
    var a;
    function fn() {
        var b = 2;
        //  var c = 3;
        function fn2() {
            console.log(a);
            console.log(c);
        }
        fn2();
        var c = 3;
    }
    fn();
    a = 100;
    
    作用域.png

    作用域链:寻找变量,只会“往上”!!!不会“往下”!!!

    拓展:

    JavaScript 开发进阶:理解 JavaScript 作用域和作用域链

    补充:

    1. return

    有时候我们希望在函数执行后给我们一个反馈,就像表达式一样,给我们个结果,我们可以通过return来实现

    这样我们就能拿到函数希望给我的反馈了,调用return后,函数立即中断并返回结果,即使后面还有语句也不再执行

    function sayName(name) {
        if(typeof name !== 'string') {
            return ;
        }
        console.log("hello ", name);
    }
    sayName(12);
    sayName("Tim");
    

    如果传入参数不是字符串,这里的 return 会跳出函数

    注意区别:,break 和 continue。

    break 和 continue,是跳出循环。return 是跳出函数

    return 只有在函数里面用!!!

    2. 命名冲突

    当在同一个作用域内定义了名字相同的变量和方法的话,无论其顺序如何,变量的赋值会覆盖方法的声明

    当函数执行有命名冲突的时候,函数执行时载入顺序是:变量、函数、参数

    function fn2(fn2) {
        console.log(fn2);
        var fn2 = 3;
        console.log(fn2);
        function fn2() {
            console.log('fnnn2');
        }
    }
    
    fn2(10);
    

    实际上,会像下面执行语句

    function fn2(fn2) {
        var fn2;
        function fn2(){
            console.log('fnnn2');
        }
        
        console.log(fn2);
        fn2 = 3;
        console.log(fn2);
    }
    
    fn2(10);
    
    命名冲突.png
    再补充:
    var abc = 100;
    var abc;
    

    另外,作用域这个概念只适用于函数,平常的变量声明和循环都没有作用域这个概念。

    这时,abc 并不是100,100并没有被抹掉。

    3. 作用域

    function fn() {
        console.log(i);
        var i = 99;
        
        function fn2() {
            i = 100;
        }
        fn2();
        console.log(i);
    }
    fn();
    console.log(i);
    
    父子-作用域.png

    function fn2(){} 里面的 i=100 ,因为没有声明 i ,所以从上一级作用域去找,(找到了 var i=99;),然后将 i 赋值为 100。这样,就改变了 fn 里面声明的这个 i 的值了。

    代码:

    1. 以下代码输出什么?为什么?

        function getInfo(name, age, sex){
            console.log('name:',name);
            console.log('age:', age);
            console.log('sex:', sex);
            console.log(arguments);
            arguments[0] = 'valley';
            console.log('name', name);
        }
    
        getInfo('hunger', 28, '男');
        getInfo('hunger', 28);
        getInfo('男');
    
    代码1.png

    2. 写一个函数,返回参数的平方和?

    function sumOfSquares() {
        var sum = 0;
        for (var i=0; i<arguments.length; i++) {
            sum = sum + arguments[i] * arguments[i];
        }
        return sum;
    }
    

    3. 如下代码的输出?为什么?

    console.log(a);
    var a = 1;
    console.log(b);
    
    代码3.png

    4. 如下代码的输出?为什么?

    sayName('world');
    sayAge(10);
    function sayName(name){
        console.log('hello ', name);
        }
    var sayAge = function(age){
        console.log(age);
    };
    
    代码4.png

    sayAge 只是函数表达式,不会有“函数声明前置”,只有“变量声明前置”。

    5. 如下代码的输出?为什么?

    function fn(){}
    var fn = 3;
    console.log(fn);
    
    代码5.png

    6. 如下代码的输出?为什么?

    function fn(fn2){
        console.log(fn2);
        var fn2 = 3;
        console.log(fn2);
        console.log(fn);
        function fn2(){
            console.log('fnnn2');
        }
    }
    fn(10);
    
    代码6.png

    实际代码执行如下:

    function fn(fn2) {
        var fn2;
        function fn2() {
            console.log('fnnn2');
        }
        console.log(fn2);
        fn2 = 3;
        console.log(fn2);
        console.log(fn);
    }
    

    7. 如下代码的输出?为什么?

    var fn = 1;
    function fn(fn){
        console.log(fn);
    }
    console.log(fn(fn)); 
    
    代码7.png

    实际代码执行如下:

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

    8. 如下代码的输出?为什么?

    //作用域
    console.log(j);
    console.log(i);
    for(var i=0; i<10; i++){
        var j = 100;
    }
    console.log(i);
    console.log(j);
    
    代码8.png

    实际代码执行如下:

    var i;
    var j;
    console.log(j);
    console.log(i);
    for (i=0; i<10; i++) {
        j = 100;
    }
    console.log(i);
    console.log(j);
    

    9. 如下代码的输出?为什么?

    fn();
    var i = 10;
    var fn = 20;
    console.log(i);
    function fn(){
        console.log(i);
        var i = 99;
        fn2();
        console.log(i);
        function fn2(){
            i = 100;  //这里的 i 对于 fn 来说,是"全局"变量
        }
    }
    
    代码9.png

    10. 如下代码的输出?为什么?

    var say = 0;
    (function say(n){
        console.log(n);
        if(n<3) return;
        say(n-1);
    }( 10 ));
    console.log(say);
    
    代码10.png

    这个“立即执行函数”是语句,而不是函数。而且它包裹的这段代码拥有自己的作用域!

    相关文章

      网友评论

          本文标题:JavaScript2

          本文链接:https://www.haomeiwen.com/subject/cdvlettx.html