1.函数声明和函数表达式有什么区别
函数声明
声明不必放到调用的前面
//函数声明
function sayHello(){
console.log('hello')
}
//函数调用
sayHello()
函数表达式
声明必须放到调用的前面
var sayHello = function(){
console.log('hello');
}
sayHello()
2.什么是变量的声明前置?什么是函数的声明前置
变量的声明前置
console.log(a); //undefined
var a = 3;
console.log(a); //3
在一个作用域下,上述代码在执行时是按照以下方式执行
var a//先把变量的声明提到最前,此时a是undefined
console.log(a)//所以得到undefined
a=3//给a赋值3
console.log(a)//输出a为3
函数的声明前置
sayHello();
function sayHello(){
console.log('hello');
}
在一个作用域下,上述代码在执行时是按照以下方式执行
function sayHello(){ //首先将函数的声明提到最前
console.log('hello');
}
sayHello(); //得到输出"hello"
3.arguments 是什么?
arguments是函数所有传入参数的一个集合,是一个类数组对象
可以使用arguments对象获取到该函数的所有传入参数
function printPersonInfo(name, age, sex){
console.log(arguments[0]);
console.log(arguments[1]);
console.log(arguments[2]);
}
printPersonInfo('小明',2, 'male')// '小明' 2 'male'
4.函数的"重载"怎样实现
在函数体针对不同的参数调用执行相应的逻辑
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'
5.立即执行函数表达式是什么?有什么作用
(function(){
var a = 1;
})()
作用: 隔离作用域
6.求n!,用递归来实现
function factor(n){
if(n<0){
return "请输入大于等于0的数";
}else if( n===0 || n===1){
return 1
}
else {
return (n * factor(n-1))
}
}
7.以下代码输出什么?
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
8.写一个函数,返回参数的平方和?
function sumOfSquares(){
var total = 0;
for(var i = 0;i<arguments.length;i++){
total+=(arguments[i]*arguments[i]);
}
return total;
}
var result = sumOfSquares(2,3,4)
var result2 = sumOfSquares(1,3)
console.log(result) //29
console.log(result2) //10
9.如下代码的输出?为什么
console.log(a);//undefined
var a = 1;
console.log(b);//b is not defined
原因: 因为变量声明被前置了,所以console.log(a)
的时候输出的a
未被赋值,还是undefined
,后面的console.log(b)
为b is not defined
,意思为b未定义。
10.如下代码的输出?为什么
sayName('world'); // hello world
sayAge(10); //sayAge is not a function(…)
function sayName(name){
console.log('hello ', name);
}
var sayAge = function(age){
console.log(age);
};
原因:函数声明被前置了,函数表达式不会被前置。执行情况如下:
function sayName(name){
console.log('hello ', name);
}
var sayAge
sayName('world'); // hello world
sayAge(10); //sayAge is not a function(…)
sayAge = function(age){
console.log(age);
};
11.如下代码输出什么? 写出作用域链查找过程伪代码
var x = 10
bar() //10
function foo() {
console.log(x)
}
function bar(){
var x = 30
foo()
}
作用域链查找过程:
1.最开始是全局作用域
globalContext = {
AO: {
x: 10
foo: function
bar: function
},
Scope: null
}
//声明 foo 时 得到下面
foo.[[scope]] = globalContext.AO
//声明 bar 时 得到下面
bar.[[scope]] = globalContext.AO
2.当调用 bar() 时, 进入 bar 的执行上下文
barContext = {
AO: {
x: 30
},
Scope: bar.[[scope]] //globalContext.AO
}
3.当调用 foo() 时,先从 bar 执行上下文中的 AO里找,找不到再从 bar 的 [[scope]]里找,找到后即调用
4.当调用 foo() 时,进入 foo 的执行上下文
fooContext = {
AO: {},
Scope: foo.[[scope]] // globalContext.AO
}
所以最后结果是10
12.如下代码输出什么? 写出作用域链查找过程伪代码
var x = 10;
bar() //30
function bar(){
var x = 30;
function foo(){
console.log(x)
}
foo();
}
作用域链查找过程:
1.全局作用域
globalContext = {
AO: {
x: 10
bar: function
},
Scope: null
}
//声明 bar 时 得到下面
bar.[[scope]] = globalContext.AO
2.当调用 bar() 时, 进入 bar 的执行上下文
barContext = {
AO: {
x: 30,
foo: function
},
Scope: bar.[[scope]] //globalContext.AO
}
//在 bar 的执行上下文里声明 foo 时 得到下面
foo.[[scope]] = barContext.AO`
3.当调用 foo() 时,先从 bar 执行上下文中的 AO里找,找到后即调用
4.当调用 foo() 时,进入 foo 的执行上下文
fooContext = {
AO: {},
Scope: foo.[[scope]] // barContext.AO
}
5.在foo的执行上下文的AO里找x,没找到就在它scope里找,在 bar()的AO里找到x=30所以得到结果为30
13.以下代码输出什么? 写出作用域链的查找过程伪代码
var x = 10;
bar() //30
function bar(){
var x = 30;
(function (){
console.log(x)
})()
}
作用域链的查找过程:
前几步都与上面一个问题的步骤相同,却别在于立即执行函数:
全局作用域 => 当调用 bar() 时, 进入 bar 的执行上下文 => 当调用立即执行函数时,先从 bar 执行上下文中的 AO里找,找到后即调用 => 进入立即执行函数的执行上下文 => 在立即执行函数的执行上下文的AO里找x,没找到就在它scope里找,在 bar()的AO里找到x=30所以得到结果为30。
14.以下代码输出什么? 写出作用域链查找过程伪代码
var a = 1;
function fn(){
console.log(a)//undefined
var a = 5
console.log(a)//5
a++
var a
fn3()
fn2()
console.log(a)//20
function fn2(){
console.log(a)//6
a = 20
}
}
function fn3(){
console.log(a)//1
a = 200
}
fn()
console.log(a)//200
作用域链查找过程:
/*
1.全局作用域
globalContext={
AO:{
a:1,
fn:function(){},
fn3:function(){}
}
scope:null
}
fn[[scope]]= globalContext.AO
fn3[[scope]]= globalConetx.AO
2.调用fn(),进入fn的执行上下文
fnContext={
AO:{
a:5,
fn3:undefined,
fn2:undefined
}
scope:globalContext.AO
}
fn执行第一行时a声明前置没有赋值 输出undefined,接着a被赋值5
执行第二个console.log(a) 输出5
a++ a变为6
fnContext={
AO:{
a:6,
fn3:undefined,
fn2:undefined
}
scope:globalContext.AO
}
3.调用fn3(),进入fn3的执行上下文
fn3Context={
AO:{
}
scope:globalContext.AO
}
4.执行fn3里的console.log(a),先在fn3的执行上下文里找a,没找到在scope里找,找到a为1。
5.给a赋值200,fn3的AO里没有a,在scope里找到,使得globalContext的AO的a被赋值为200
globalContext={
AO:{
a:200,
fn:function(){},
fn3:function(){}
}
scope:null
}
fn[[scope]]= globalContext.AO
fn3[[scope]]= globalConetx.AO
6.执行fn2(),进入fn2的执行上下文
fn2Context={
AO:{
}
scope:fnContext.AO
}
7.执行fn3里的console.log(a),先在fn2的执行上下文里的AO里找a,没找到,就去它的scope里找,得到值是6
8.给a赋值20,fn2的AO里没有a,在scope里找到,使得fnContext的AO的a被赋值为20
9.console.log(a),在它所属的fn的执行上下文里的AO里找到a为20
10.fn()执行完毕,执行console.log(a),其所在的全局执行上下文中目前a的值为200。