JS 函数相关知识,重点:作用域链

问答题

1.函数声明和函数表达式有什么区别 (*)

关键词function声明一个函数; ()为占位符形参,而在调用函数时候传入的值叫实参,函数可有多个参数;

  • 函数声明:

    function functionName(){
    statement;
    }

  • 函数表达式: 将函数赋值,最后有分号断句.


    var printName = function(){
    console.log('Byron');
    };

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

  • 例如:

    var a =1 ;
    var b = function doSomething(){
    console.log(b)
    }
    console.log(a); // 1
    doSomething(b);
    // function doSomething(){
    console.log(b)
    }
  • 上述变量和函数声明提前则如下:

    var a ;
    var b ;
    a = 1;
    b = function doSomething(){
    console.log(b)
    }
    console.log(a); // 1
    doSomething(b);
    // function doSomething(){
    console.log(b)
    }

3.arguments 是什么 (*)

函数内部,可以用arguments对象获取到该函数的所有传入参数;
eg:


function printPersonInfo(name, age, sex){
console.log('name:',name);
console.log('age:',age);
console.log('sex:',sex);
console.log(arguments);
}
printPersonInfo('jack',18,'男');
// name: jack
// age: 18
// sex: 男
//以下是arguments作用显示
// ["jack", 18, "男"]
// 0: "jack"
// 1: 18
// 2: "男"
// callee: printPersonInfo(name, age, sex)
// length: 3
// Symbol(Symbol.iterator): values()
// proto: Object

4.函数的重载怎样实现 (**)

JavaScript中没有函数重载的概念,JS是通过函数名字确定唯一性,参数不影响函数,只有函数名会影响,后面的会覆盖前面的;
JavaScript中没必要传入多有参数,只需函数体内处理即可,但前提是传的参数永远被当做是前几个


function printPeopleInfo(name, age, sex){
if(name){
console.log(name);
}

if(age){
    console.log(age);
}

if(sex){
    console.log(sex);
}

}

printPeopleInfo('Byron', 26);// Byron 26
printPeopleInfo('Byron', 26, 'male'); // Byron 26 male
printPeopleInfo('male');// male

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


(function functionName(){
})();
或者
( function(){
}() );

作用: 不会受到声明前置的影响;

var i = 99;

(function (n){
var i = 88;
console.log(n);
console.log('hello world',i);
if (n<0) return;
//say (n-1);
})(100);

console.log(i);

打印结果如下:
// 100
// hello world 88
// 99

6.什么是函数的作用域链 (****)

JavaScript的*作用域*是靠函数来形成的,一个函数内定义的变量函数外不可以访问,
*作用域链*:函数对象和其它对象一样,拥有可以通过代码访问的属性和一系列仅供JavaScript引擎访问的内部属性.其中一个内部属性是[[Scope]],由ECMA-262标准第三版定义,该内部属性包含了函数被创建的作用域中对象的集合,这个集合被称为函数的*作用域链*,它决定了哪些数据能被函数访问。
注意: 由于JavaScript的函数可以嵌套,此时,内部函数可以访问外部函数定义的变量,反过来则不行。任何变量(函数也视为变量),如果没有在当前函数作用域中找到,就会继续往上查找,最后如果在全局作用域中也没有找到,则报ReferenceError错误。JavaScript的函数在查找变量时从自身函数定义开始,从“内”向“外”查找。如果内部函数定义了与外部函数重名的变量,则内部函数的变量将“屏蔽”外部函数的变量。

作用域链参考资料

代码题

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. getInfo('hunger', 28, '男');

name: hunger
age: 28
sex: 男
["hunger", 28, "男"]
name: valley

  1. getInfo('hunger', 28);

name: hunger
age: 28
sex: undefined
["hunger", 28]
name: valley

  1. getInfo('男');

name: 男
age: undefined
sex: undefined
['男']
name: valley

2.写一个函数,返回参数的平方和?如 (难度**)


function sumOfSquares(){
var sumOfSquares = 0;
for(var i=0; i < arguments.length;i++){
sumOfSquares = sumOfSquares + arguments[i]*arguments[i]
}
return sumOfSquares;
}
打印结果:
console.log(sumOfSquares(2,3,4)); //29
console.log(sumOfSquares(1,3)); //10

3.如下代码的输出?为什么 (难度*)


console.log(a);
var a = 1;
console.log(b);

原因:变量声明前置
输出如下:
var a
console.log(a); //undefiend
a = 1;
console.log(b); // b is not defined

4.如下代码的输出?为什么 (难度*)


sayName('world');
sayAge(10);
function sayName(name){
console.log('hello ', name);
}
var sayAge = function(age){
console.log(age);
};
原因:函数声明前置 , 函数表达式没有前置
输出如下:
var sayAge;
function sayName(name){
console.log('hello ', name); //hello world
}

sayName('world'); 
sayAge(10); 

sayAge = function(age){
console.log(age); // sayAge is not a function
};

5.如下代码的输出?为什么 (难度**)


function fn(){}
var fn = 3;
console.log(fn);
输出: // 3
原因:声明前置
var fn;
function fn(){}

fn=3;
console.log(fn)

6.如下代码的输出?为什么 (难度***)


function fn(fn2){
console.log(fn2);
var fn2 = 3;
console.log(fn2);
console.log(fn);
function fn2(){
console.log('fnnn2');
}
}
fn(10);
原因和输出: 1.声明前置,函数声明>变量声明;
// function fn2(){
console.log('fnnn2');
}
2. fn2=3;
// 3
3. 打印外面的fn
// function fn(fn2){
console.log(fn2);
var fn2 = 3;
console.log(fn2);
console.log(fn);
function fn2(){
console.log('fnnn2');
}
}
4. fn(10); 只是赋值调用函数,并未执行输出
|
原因: 函数声明前置
function fn(fn2){
var fn2;
function fn2(){
console.log('fnnn2');
}

   console.log(fn2);
   fn2 = 3;
   console.log(fn2);
   console.log(fn);
   
 }
fn(10);

          [demo参考](http://js.jirengu.com/qamo/2/edit) 

7.如下代码的输出?为什么 (难度***)


var fn = 1;
function fn(fn){
console.log(fn);
}
console.log(fn(fn));
输出:// 报错 fn is not a function
原因:fn =1 时,fn被赋值为1, fn不再是函数
var fn;
function fn(fn){
console.log(fn);
}

fn = 1;   //fn被赋值为1,fn 不再是函数
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);
输出:
console.log(j); // undefined
console.log(i); // undefined
for(var i=0; i<10; i++){
var j = 100;
} // var i=10 ;var j=100;并生成全局变量;
console.log(i); // 10
console.log(j); // 100

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;
}
}

输出:如下:
原因:作用域链是从里往外找, 外面的只会在当前领域或者向上向父亲领域找,直到找到全局变量为止
var i;
var fn;
function fn(){
var i;
function fn2(){
i = 100;
}

   console.log(i);  //  undefined
   i = 99;
   fn2();
   console.log(i);    // 100    
}


fn();
 i = 10;
fn = 20;
console.log(i);// 10

10.如下代码的输出?为什么 (难度*****)


var say = 0;
(function say(n){
console.log(n);
if(n<3) return;
say(n-1);
}( 10 ));
console.log(say);
输出:如下
原因:1.立刻执行函数执行完就销毁,拥有自己的作用域
2.立刻执行函数的东西不会前置和提升
var say;

say = 0;
(function say(n){
    console.log(n);
    if(n<3) return;// 递归,赋值为10的时候得到 n-1=9,然后n=9;继续循环,直到n=2时候,满足 if 条件,return终止,不执行 n-1;所以最后结果为2
    say(n-1);
}( 10 ));  // 10,9,8,7,6,5,4,3,2 
console.log(say); //  0

  • 本文章著作权归(风骨来客qq:2361597776)和饥人谷(QQ 群: 222459918) 所有,转载须说明来源

你可能感兴趣的:(JS 函数相关知识,重点:作用域链)