1. 函数声明和函数表达式有什么区别
函数声明:function fnname (){函数体}
函数表达式:var fnname=function(){函数体}
使用function关键字可以声明一个函数,它的特征是函数声明提升,执行代码前会先读取函数声明,即函数声明不必放在调用的前面,它可以放在当前作用域任何位置;函数表达式在使用前必须先赋值,所以声明必须放在调用前面,不然浏览器解析代码时会认为函数还不存在而抛出错误,理解函数提升的关键就是理解函数声明与函数表达式之间的区别。
2. 什么是变量的声明前置?什么是函数的声明前置
变量的声明前置:在程序运行前,先获取变量的名字,并将其提升到当前作用域的头部,到该变量的赋值语句,为该变量赋值,在此前都是undefined。
变量的声明前置位置:变量提升到其所处作用域的顶部;函数内的变量,则提升到函数内的顶部。
函数的声明前置:function 函数名(){}声明了一个函数,在程序运行前,提取所有函数声明的函数名,提升到作用域的头部,之后才正式开始运行函数,所以,无论函数声明的函数执行语句放在程序的最前面,或者程序的最后面,都能够正常执行
函数声明前置:提升到其所处作用域的顶部,函数内的函数,提升到函数内的顶部。
3. arguments 是什么
类数组对象,在函数内部,你可以使用arguments对象获取到该函数的所有传入参数,通过访问arguments对象的length属性可以获知有多少个参数传递给了函数。而且arguments的值会与对应命名的参数值保持同步,没有传递值的命名参数会自动赋值为undefined。
arguments.png
4. 函数的"重载"怎样实现
概念:函数重载指同一函数名对应着多个函数的实现。即每种实现对应一个函数体,这些函数名字相同,但参数类型或个数或顺序不同。
基本设计原则:当两个函数除了参数类型和参数个数不同以外其他功能完全相同时,利用函数重载;两个函数功能不同时不应使用重载,而应使用一个名字不同的函数。
//其他语言重载范例
int sum(int num1, int num2){
return num1 + num2;
}
float sum(float num1, float num2){
return num1 + num2;
}
sum(1, 2);
sum(1.5, 2.4);
js是弱类型语言,参数不是固定的某个类型,所以在js中没有重载,同名函数后面的会覆盖前面的。但我们也可以实现重载所需要的功能。
function printPeopleInfo(name,age,sex){
if(name){
console.log(name);
}
if(age){
console.log(age);
}
if(sex){
console.log(sex);
}
}
printPeopleInfo("dot",23); //dot 23
printPeopleInfo("dot","female",23); //dot female 23
注意:始终记住函数名只是一个指向函数对象的指针,并不会与某个函数绑定。
5. 立即执行函数表达式是什么?有什么作用
立即执行函数表达式:缩写IIFE,是一种利用javascript函数生成新作用域的编程方法,也叫自执行函数。
作用:
- 令函数中声明的变量绕过js的变量置顶声明规则
- 避免新的变量被解释成全局变量或函数名占用全局变量名的情况
- 在禁止访问函数內变量声明的情况下允许外部对函数的调用
实现:因js里的()里不能包含语句,所以解析器会将()里的代码解析成function表达式并立即执行。
// 以下都能实现立即执行
(function(){ /* code */ }());
(function(){ /* code */ })();
// function前加一元运算符也可实现,advance-task2我有提到过
!function () { /* code */ } ();
~function () { /* code */ } ();
-function () { /* code */ } ();
+function () { /* code */ } ();
6. 求n!,用递归来实现
function fun(num) {
if (num == 1 || num == 0) {
return 1
} else if (num < 1) { return false }
return num*fun(num-1)
}
//n! (n的阶乘)这道题,由于 0! = 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('男');
name: 饥人谷
age: 2
sex: 男
["饥人谷",2,"男"]
name: valley
name: 小谷
age: 3
sex: undefined
["小谷",3]
name: valley
name: 男
age: undefined
sex: undefined
["男"]
name:valley
8. 写一个函数,返回参数的平方和?
function sumOfSquares(){
var res = 0;
for (var i in arguments){
if (typeof arguments[i] !== 'number') {
return 'you entered a wrong number';
}
}
for (var j in arguments){
res += arguments[j]*arguments[j];
}
return res;
}
var result = sumOfSquares(2,3,4);
var result2 = sumOfSquares(1,3);
console.log(result); //29
console.log(result2); //10
9. 如下代码的输出?为什么
console.log(a); //undefined,因为变量a声明提升并赋值为undefined,先读取变量声明
var a = 1;
console.log(b); //ReferenceError:b is not defined,因为b没有声明
10. 如下代码的输出?为什么
sayName('world'); //hello world 函数声明前置,
sayAge(10); //报错:say age is not a function,因为sayAge是函数表达式,使用前必须赋值,而声明放在了调用的后面,此时函数还不存在,所以会报错
function sayName(name){
console.log('hello ', name);
}
var sayAge = function(age){
console.log(age);
};
11. 如下代码输出什么? 写出作用域链查找过程伪代码
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()
console.log(a)
//为了更好的理解上面的函数 下面我来改写一下
var a = 1;
function fn(){
console.log(_a)
var _a = 5 //var a变量提升
console.log(_a)
_a++
var _a
fn3() // 执行fn3 函数
fn2() // 执行fn2 函数
console.log(_a)
function fn2(){
console.log(_a)
_a = 20
}
}
function fn3(){
console.log(a)
a = 200
}
fn()
console.log(a)
12. 如下代码输出什么? 写出作用域链查找过程伪代码
var x = 10;
bar()
function bar(){
var x = 30;
function foo(){
console.log(x)
}
foo();
}
输出30
gobalContext = {
AO: {
x:10,
foo: function(){}
},
Scope: null
}
bar.[[scope]] = gobalContext.AO
barContext = {
AO:{
x:30,
foo: function(){}
},
Scope: gobalContext.AO
}
13. 以下代码输出什么? 写出作用域链的查找过程伪代码
var x = 10;
bar()
function bar(){
var x = 30;
(function (){
console.log(x)
})()
}
30
gobalContext = {
AO: {
x: 10,
bar: function(){}
},
Scope: null
}
bar.[[scope]] = gobalContext.AO;
barContext = {
AO: {
x: 30,
IIFE: function(){}
},
Scope: gobalContext.AO;
};
IIFEContext = {
AO: {
},
Scope: barContext.AO
}
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
gobalContext = {
AO: {
a:1,
fn: function(){},
fn3: function(){}
},
Scope: null
};
fn[Scope] = gobalContext.AO;
fn3[Scope] = gobalContext.AO;
fnContext = {
AO: {
a: 20,
fn2: function(){}
}
Scope: gobalContext.AO;
};
fn3Context = {
AO: {
},
Scope: gobalContext.AO;
};
fn2Context = {
AO: {
},
Scope: fnContext.AO
}
网友评论