函数声明和函数表达式有什么区别
- 函数声明必须有标识符,也就是常说的函数名;函数表达式可以省略函数名。
- 函数声明会提前,函数声明的话函数可以提前调用,而函数表达式是什么时候遇到什么时候执行。
- 以函数声明的方法定义的函数并不是真正的声明,它们仅仅可以出现在全局中,或者嵌套在其他的函数中,但是它们不能出现在循环,条件或者try/catch/finally中,而函数表达式可以在任何地方声明。
什么是变量的声明前置?什么是函数的声明前置?
变量提升:当一个变量被定义时,在代码执行前会先将变量进行初始化再执行语句。函数提升:当函数以函数声明的方式声明时,代码执行前会首先生成该函数,然后再执行语句。
arguments 是什么?
- 在函数代码中,使用特殊对象 arguments,开发者无需明确指出参数名,就能访问它们。
例如,在函数 sayHi() 中,第一个参数是 message。用 arguments[0] 也可以访问这个值,即第一个参数的值(第一个参数位于位置 0,第二个参数位于位置 1,依此类推)。 - 检测参数个数
还可以用 arguments 对象检测函数的参数个数,引用属性 arguments.length 即可。
模拟函数重载
函数的"重载"怎样实现?
重载是很多面向对象语言实现多态的手段之一,在静态语言中确定一个函数的手段是靠方法签名——函数名+参数列表,也就是说相同名字的函数参数个数不同或者顺序不同都被认为是不同的函数,称为函数重载。
在JavaScript中没有函数重载的概念,函数通过名字确定唯一性,参数不同也被认为是相同的函数,后面的覆盖前面的,但可以在函数体针对不同的参数调用执行相应的逻辑。
用 arguments 对象判断传递给函数的参数个数,即可模拟函数重载:
function doAdd() {
if(arguments.length == 1) {
alert(arguments[0] + 5);
} else if(arguments.length == 2) {
alert(arguments[0] + arguments[1]);
}
}
doAdd(10); //输出 "15"
doAdd(40, 20); //输出 "60"
立即执行函数表达式是什么?有什么作用?
定义一个函数,然后立即调用它。
(function(){
var a = 1;
})()
其他写法:
(function fn1() {});
[function fn2() {}];
1, function fn3() {};
作用:隔离作用域。
求n!,用递归来实现
function factor(n){
if(n > 1){
n = factor(n-1)*n
return(n)
}else{
return(n = 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, '男');//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
写一个函数,返回参数的平方和?
function sumOfSquares() {
var sum = 0;
for (i = 0;i<arguments.length;i++){
sum = arguments[i]*arguments[i] + sum;
}
console.log(sum);
}
var result = sumOfSquares(2,3,4)
var result2 = sumOfSquares(1,3)
console.log(result) //29
console.log(result2) //10
如下代码的输出?为什么
console.log(a);//undefined
var a = 1;
console.log(b);//报错
//实际按照如下执行,b没有定义故报错。
var a;
console.log(a);
a = 1;
console.log(b);
如下代码的输出?为什么
sayName('world');//输出hello world,函数的声明会被前置
sayAge(10);//报错,函数的表达式会被忽略掉,更不会被前置
function sayName(name){
console.log('hello ', name);
}
var sayAge = function(age){
console.log(age);
};
//hello world 10
如下代码输出什么? 写出作用域链查找过程伪代码
var x = 10
bar() //输出10
function foo() {
console.log(x)
}
function bar(){
var x = 30
foo()
}
//
globalContext{
AO:{
x = 10;
foo:function;
bar:function;
}
Scope:null;
}
//声明 foo 时 得到下面
foo.[[scope]] = globalContext.AO
//声明 bar 时 得到下面
bar.[[scope]] = globalContext.AO
barContext{
AO:{
x = 30;
}
Scope:bar[[scope]];//globalContext.AO
}
fooContext{
AO:{ }
Scope:foo[[scope]];//globalContext.AO
}
如下代码输出什么? 写出作用域链查找过程伪代码
var x = 10;
bar() //输出30
function bar(){
var x = 30;
function foo(){
console.log(x)
}
foo();
}
//
globalContext{
AO:{
x = 10;
bar:function;
}
Scope:null;
}
//声明 foo 时 得到下面
foo.[[scope]] = barContext.AO
//声明 bar 时 得到下面
bar.[[scope]] = globalContext.AO
barContext{
AO:{
x = 30;
foo:function;
}
Scope:bar[[scope]];//globalContext.AO
}
fooContext{
AO:{ }
Scope:foo[[scope]];//barContext.AO
}
以下代码输出什么? 写出作用域链的查找过程伪代码
var x = 10;
bar() //输出30
function bar(){
var x = 30;
(function (){
console.log(x)
})()
}
//
globalContext{
AO:{
x = 10;
bar:function;
}
Scope:null;
}
//声明 bar 时 得到下面
bar.[[scope]] = globalContext.AO
barContext{
AO:{
x = 30;
}
Scope:bar[[scope]];//globalContext.AO
}
以下代码输出什么? 写出作用域链查找过程伪代码
var a = 1;
function fn(){
console.log(a)//声明前置。输出undefined
var a = 5
console.log(a)//输出5
a++
var a
fn3()//输出1
fn2()//输出6
console.log(a)输出20
function fn2(){
console.log(a)
a = 20
}
}
function fn3(){
console.log(a)
a = 200
}
fn()
console.log(a)//输出200
//
globalContext{
AO:{
a = 1;
fn:function;
fn3:function;
}
Scope:null;
}
//声明 fn 时 得到下面
fn.[[scope]] = globalContext.AO
//声明 fn2 时 得到下面
fn2.[[scope]] = fnContext.AO
//声明 fn3 时 得到下面
fn3.[[scope]] = globalContext.AO
fnContext{
AO:{
a = 5;
fn2:function;
}
Scope:bar[[scope]];//globalContext.AO
}
fn3Context{
AO:{
a = 200;
}
Scope:foo[[scope]];//globalContext.AO
}
fn2Context{
AO:{
a = 20;
}
Scope:foo[[scope]];//fnContext.AO
}