JS-函数和作用域知多少

JS-函数和作用域知多少

1.函数声明和函数表达式是声明函数的两种不同的方式,形式如下:

函数声明:即使用function关键字声明一个函数

//函数声明

function sayHello(){

console.log(‘hello’)

}

//函数调用

sayHello()

声明不必放到调用的前面,函数调用可以发生在函数声明之前,例如下面这种情况下不会报错

printName();//输出console.log(‘1’)

function printName(){

console.log(‘1’);

}

//正常,因为提升了函数声明,函数调用可在函数声明之前

即在一个作用域下,var 声明的变量和function 声明的函数会前置

函数表达式

var sayHello = function(){

console.log(‘hello’);

}

sayHello()

声明必须放到调用的前面,例如

printName();//浏览器提示Uncaught TypeError: printName is not a function(…)

var printName = function(){

console.log(‘1’);

};

//报错,函数表达式和 var 一个变量没什么区别,变量printName还未保存对函数的引用,函数调用必须在函数表达式之后

浏览器提示Uncaught TypeError: printName is not a function(…).原因:类似变量提升,函数作为一个变量赋值给printName,等价于

var printName; //此时printName为undefined

printName();

printName = function(){

console.log(‘1’);

};

因此,函数声明和函数表达式不同之处在于:

Javascript引擎在解析javascript代码时会‘函数声明提升’(Function declaration Hoisting)当前执行环境(作用域)上的函数声明,而函数表达式必须等到Javascirtp引擎执行到它所在行时,才会从上而下一行一行地解析函数表达式,

函数表达式后面可以加括号立即调用该函数,函数声明不可以,只能以fnName()形式调用

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

变量声明前置

JavaScript引擎的工作方式是,先解析代码,获取所有被声明的变量,然后再一行一行地运行。这造成的结果,就是所有的变量的声明语句,都会被提升到当前作用域的头部,这就叫做变量的声明前置,也叫变量提升(hoisting)。

函数声明前置

JavaScript引擎将函数名视同变量名,所以采用function命令声明函数时,函数声明会像变量声明一样,被提升到代码头部。因此,函数的调用可以写在声明前面,函数可以被执行。(注意:如下函数表达式,变量fn还未保存对函数的引用,函数调用必须在函数表达式之后)。

console.log(fn); //undefined

fn(); //浏览器提示Uncaught TypeError: fn is not a function(…)

var fn = function(){}

//报错,变量fn还未保存对函数的引用,函数调用必须在函数表达式之后

3.arguments 是什么

arguments是一个类数组对象,类似数组的方式,可以通过下标的方式去获取值,但它本身不是数组,没有数组的一些特性,所以叫类数组对象。在函数内部,可以使用arguments对象获取到该函数的所有传入参数。

例如如下函数

function printPersonInfo(name, age, sex){

console.log(name);

console.log(age);

console.log(sex);

console.log(arguments);

}

执行printPersonInfo(‘liu’, 21, ‘boy’)后,输出:

name : liu

age : 22

sex : boy

[“liu”, 22, “boy”]

执行printPersonInfo(‘liu’, 21, ‘boy’)后,输出:

name : liu

age : boy

sex : undefined

[“liu”, “boy”]

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

重载是指不同的函数使用相同的函数名,但是函数的参数个数或类型不同。调用的时候根据函数的参数来区别不同的函数。

JS并不像其他强类型语言一样可以声明重载函数,若在原先声明的函数后再声明一个不同参数数量的函数(JS是弱语言,声明的函数不需要指明参数类型),解析器会用后面声明的函数覆盖前面声明的函数。

JS种没有重载! 同名函数会覆盖。但可以在函数体针对不同的参数调用执行相应的逻辑,如下

function printPeopleInfo(name, age, sex){

if(name){

console.log(name);

}

if(age){

console.log(age);

}

if(sex){

console.log(sex);

}

}

printPeopleInfo(‘Byron’, 26);

printPeopleInfo(‘Byron’, 26, ‘male’);

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

(function(){ var a=1; })();

(function(){ var a=1; }());

作用:

作用:隔离作用域。

6.递归

递归实现一个函数,计算 n!

function factor(n) {

if(n===1){

return n

}

return n*factor(n-1)

}

JS-函数和作用域知多少

几个代码小题目

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(‘饥人谷’, 2, ‘男’);

getInfo(‘小谷’, 3);

getInfo(‘男’);

  • getInfo(‘饥人谷’, 2, ‘男’);输出:

  • name:饥人谷

    age:2

    sex:男

    [“饥人谷”, 2, “男”]

    name valley

  • getInfo(‘小谷’, 3);输出:

  • name:小谷

    age:3

    sex:undefined

    [“小谷”, 3]

    name valley

  • getInfo(‘男’);输出:

  • name:男

    age:undefined

    sex:undefined

    [“男”]

    name valley

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

    function sumOfSquares(){

    var sum = 0

    for (var i = 0; i < arguments.length; i ++)

    sum += arguments[i] * arguments[i]

    return sum

    }

    var result = sumOfSquares(2,3,4)

    var result2 = sumOfSquares(1,3)

    console.log(result) //29

    console.log(result2) //10

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

    console.log(a);//undefined

    var a = 1;

    console.log(b);//报错Uncaught ReferenceError: b is not defined(…)

    a输出undefined是因为变量提升,b没有定义,类似如下代码

    var a;

    console.log(a); //undefined

    a = 1;

    console.log(b);

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

    sayName(‘world’); //输出 ‘hello ‘, ‘world’ 使用函数声明做出的声明前置

    sayAge(10); //报错 Uncaught TypeError: sayAge is not a function(…) sayAge此时还为被赋值为函数

    function sayName(name){

    console.log(‘hello ‘, name);

    }

    var sayAge = function(age){

    console.log(age);

    };

    作用域链

    5.如下代码输出什么? 写出作用域链查找过程伪代码

    // 输出10

    var x = 10

    bar() //输出10

    function foo() {

    console.log(x)

    }

    function bar(){

    var x = 30

    foo()

    }

    作用域链查找过程伪代码

    /*

    1.

    globalContext = {

    AO:{

    x: 10

    foo:funcation(){}

    bar:funcation(){}

    }

    Scope: null

    }

    foo.[[scope]] = globalContext.AO

    bar.[[scope]] = globalContext.AO

    2. barContext = {

    AO:{

    x: 30

    }

    scope: bar.[[scope]] // globalContext.AO

    }

    3. fooContext = {

    AO:{}

    scope: foo.[[scope]] // globalContext.AO

    }

    */

    6.如下代码输出什么? 写出作用域链查找过程伪代码

    // 输出30

    var x = 10;

    bar() //输出30

    function bar(){

    var x = 30;

    function foo(){

    console.log(x)

    }

    foo();

    }

    作用域链查找过程伪代码

    /*

    1.

    globalContext = {

    AO:{

    x: 10

    bar:funcation(){}

    }

    Scope: null

    }

    bar.[[scope]] = globalContext.AO

    2.barContext = {

    AO:{

    x: 30

    foo:funcation(){}

    }

    Scope: bar.[[scope]] // globalContext.AO

    }

    foo.[[scope]] = barContext.AO

    3. fooContext = {

    AO:{}

    Scope: foo.[[scope]] // barContext.AO

    }

    */

    7.以下代码输出什么? 写出作用域链的查找过程伪代码

    输出30

    var x = 10;

    bar()

    function bar(){

    var x = 30;

    (function (){

    console.log(x) // 30

    })()

    }

    /*

    globalContext = {

    AO:{

    x: 10

    bar:funcation(){}

    }

    Scope: null

    }

    bar.[[scope]] // globalContext.AO

    2.barContext = {

    AO:{

    x: 30

    匿名函数A:funcation(){}

    }

    Scope: bar.[[scope]] = globalContext.AO

    }

    匿名函数A.[[scope]] // barContext.AO

    3.

    匿名函数AContext = {

    AO:{}

    Scope: 匿名函数A.[[scope]] // barContext.AO

    }

    */

    8.以下代码输出什么? 写出作用域链查找过程伪代码

    var a = 1;

    function fn(){

    console.log(a)

    var a = 5

    console.log(a)

    a++

    var a

    fn3()

    fn2()

    console.log(a)

    function fn2(){

    console.log(a)

    a = 20

    }

    }

    function fn3(){

    console.log(a)

    a = 200

    }

    fn() //输出: undefined 5 1 6 20

    console.log(a) //输出: 200

    /*

    1.

    globalContext = {

    AO:{

    a: 1 -> 200

    fn:funcation(){}

    fn3:funcation(){}

    }

    Scope: null

    }

    fn.[[scope]] = globalContext.AO

    fn3.[[scope]] = globalContext.AO

    2.

    fnContext = {

    AO:{

    a: 5 -> 6 -> 20

    fn2:funcation(){}

    }

    Scope: fn.[[scope]] // globalContext.AO

    }

    fn2.[[scope]] = fnContext.AO

    3. fn3Context = {

    AO:{}

    Scope: foo.[[scope]] // globalContext.AO

    }

    4. fn2Context = {

    A:{}

    Scope: fn2.[[scope]] // fnContext.AO

    }

    */

    JS-函数和作用域知多少

    注意:在JavaScript里,每个函数,当被调用时,都会创建一个新的执行上下文。因为在函数里定义的变量和函数只能在函数内部被访问,外部无法获取;当调用函数时,函数提供的上下文就提供了一个非常简单的方法创建私有变量。

    来源:软件开拓者

    声明:本站部分文章及图片转载于互联网,内容版权归原作者所有,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!

    上一篇 2017年9月3日
    下一篇 2017年9月3日

    相关推荐