1. 函数声明和函数表达式的区别
- 函数声明:不必放在调用的前面
//函数调用
sum();
//函数声明
function sum(){
var a=1;
var b=1;
c=a+b;
return c;
}
- 函数表达式:必须放在调用的前面
var sum=function(){
var a=1;
var b=1;
c=a+b;
return c;
}
sum();
2. 变量的声明前置和函数的声明前置
- 变量的声明前置:当一个变量被定义时,在代码执行前会先将变量进行初始化再执行语句。
console.log(a); 声明前置后 var a;
var a =1; console.log(a); // undefined
console.log(a); a =1 ;
console.log(a); // 1
- 函数的声明前置:当函数以函数声明的方式声明时,代码执行前会首先生成该函数,然后再执行语句
sayHello(); 声明前置后 function sayHello(){
function sayHello(){ console.log('hello');
console.log('hello'); }
} sayHello(); //'hello'
3. arguments
arguments是一个类数组对象,可以传入function内部所有的参数(本地变量),但不是函数的属性,只在函数内部有效,写法是arguments[i]依次对参数进行访问和修改。
function printPersonInfo(name, age, sex){
console.log(name);
console.log(age);
console.log(sex);
console.log(arguments);
}
4. 实现函数的"重载"
在js中没有函数的重载,函数通过名字确定唯一性,参数不同也被认为是相同的函数,后出现的会覆盖先出现的,但可以在函数体针对不同的参数调用执行相应的逻辑,或通过arguments实现重载。
- 通过传入参数实现重载
function userInfo(name,age,sex){
if(name){
console.log(name);
}
if(age){
console.log(age);
}
if(sex){
console.log(sex);
}
}
userInfo("andy",22); //参数依次传递值,缺少的参数返回的是
undefined userInfo("andrea",20,"female");
- 通过arguments来实现重载
function sum(){
var sum =0;
for (var i =0; i<arguments.length; i++){
sum += arguments[i];
}
return sum;
}
console.log(sum(1,2,3,4)); //输出结果为10
5. 立即执行函数表达式概念和作用
(function(){
var a = 1;
console.log(a); //1
})()
console.log(a); //报错:Uncaught ReferenceError: a is not defined
其他写法
(function fn1() {
var a = 1;
console.log(a); //1
})();
console.log(a); //报错:Uncaught ReferenceError: a is not defined
// 逗号也只能操作表达式
1, function fn3(){
var a = 1;
console.log(a); //1
}();
console.log(a); //报错:Uncaught ReferenceError: a is not defined
!function(){
var a = 1;
console.log(a); //1
}();
console.log(a); //报错:Uncaught ReferenceError: a is not defined
作用:隔离作用域,防止了变量的命名冲突,形成独立的空间;可以让函数在定义后直接调用,在固有的作用域内使用,不会污染全局变量
6. 递归实现n!
function factor(n){
if(n===1||n===0){
return 1;
}
return n*factor(n-1);
}
7. 代码练习
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 result=0;
for(var i=0; i<arguments.length; i++){
result+=arguments[i]*arguments[i];
}
return result;
}
var result = sumOfSquares(2,3,4)
var result2 = sumOfSquares(1,3)
console.log(result) //29
console.log(result2) //10
9. 代码练习
变量声明前置:
var a;
console.log(a); //underfined,变量声明前置,初始值undefined
a = 1;
console.log(b); //报错:Uncaught ReferenceError:b is not defined,因为b没有声明
10. 代码练习
sayName('world')输出结果:
hello world
//函数声明不必放在调用的前面
sayAge(10)输出结果:
报错:Uncaught TypeError: sayAge is not a function
//函数表达式必须放在调用的前面
11. 代码练习
写出以下代码的输出结果和作用域链查找过程伪代码
输出结果:10
作用域链查找过程伪代码:
1.globalContext={
AO:{
x:10
foo:function
bar:function
},
Scope:null
}
foo.[[scope]]=globalContext.AO
bar.[[scope]]=globalContext.AO
2.barContext={
AO:{
x:30
},
Scope:bar.[[scope]]
}
3.fooContext={
AO:{},
Scope:foo.[[scope]]
}
12. 代码练习
写出以下代码的输出结果和作用域链查找过程伪代码
输出结果:30
作用域链查找过程伪代码:
1. globalContext={
AO:{
x:10
bar:function
},
Scope:null
}
bar.[[scope]]=globalContext.AO
2. barContext={
AO:{
x:30
foo:function
},
Scope:bar.[[scope]]
}
foo.[[scope]]=barContext.AO
3. fooContext={
AO:{},
Scope:foo.[[scope]]
}
13. 代码练习
写出以下代码的输出结果和作用域链查找过程伪代码
输出结果:30
作用域链查找过程伪代码:
1. globalContext={
AO:{
x:10
bar:function
},
Scope:null
}
bar.[[scope]]=globalContext.OA
2. barContext={
AO:{
x:30
function:function
},
Scope:bar.[[scope]]
}
function.[[scope]]=barContext.OA
3. functionContext={
AO:{},
Scope:function.[[scope]]
}
14. 代码练习
写出以下代码的输出结果和作用域链查找过程伪代码
输出结果:undefined 5 1 6 20 200
作用域链查找过程伪代码:
1. globalContext = {
AO:{
a:1 //200
fn:function
fn3:function
},
Scope:null
}
fn.[[scope]] = globalContext.AO
fn3.[[scope]] = globalContext.AO
2.调用fn()
fnContext = {
AO:{
a:undefined //5,6,20
fn2:function
},
Scope:fn.[[scope]] //globalContext.AO
}
fn2.[[scope]] = fnContext.AO
3. fn3Context = {
AO:{
a:200
},
Scope:fn3Context.[[scope]] //globalContext.AO
}
4. fn2ConText = {
AO:{
a:20
},
Scope:fn2ConText.[[scope]] //fnContext.AO
}