任务17-JS语法,JS基础2
1.函数声明和函数表达式有什么区别 ?
1.函数声明必须有标识符,也就是常说的函数名;函数表达式可以省略函数名。
2.函数声明会提前。
3.ECMAScript规范中表示,函数声明语句可以出现在全局代码中,或者内嵌在其他函数中,但是不能出现在循环、条件判、或者try/finally以及with语句中。
注:其实两者最重要的区别就是函数声明前置的问题,一定要注意这一点。
2.什么是变量的声明前置?什么是函数的声明前置?
当我们写出:
var a = 1;
function sum(){
var sum = 0;
for(var i=0;i<arguments.length;i++){
sum = sum + arguments[i];
}
return sum;
}```
实际上最终会被解析为:
var a;
function sum(){
var sum = 0;
for(var i=0;i<arguments.length;i++){
sum = sum + arguments[i];
}
return sum;
}
a = 1```
变量的声明和函数的声明都会被提到最前,顺序是先变量声明,后函数声明,后面的声明会覆盖前面的声明。
3.arguments 是什么?
arguments 是JavaScript里的一个内置对象,所有函数都有属于自己的一个arguments对象,它包括了函所要调用的参数,即使没有明确写出来,也会默认有arguments.
例:
function getInfo(name,age,sex){
console.log('name:',name);
console.log('age:',age);
console.log('sex:',sex);
console.log(arguments);
arguments[0] = 'xiaoming';
console.log('name:',name);
}
getInfo('hunger',18,'男');
}```
name,age,sex分别对应 0,1,2的位置,我们可以通过
``argumengts[0[]= 'xiaoming';``来使所有处于 0 位置的变量为 ‘xiaoming'
##4.函数的重载怎样实现?
ECMAscript函数不能像传统意义上那样实现重载,一旦对函数声明了两次,函数会默认使后者覆盖前者。我们可以使用其他方式来实现重载效果:
function sum() {
var sum = 0;
for (var !=0;i<arguments.length;i++) {
sum = sum + arguments[i];
}
return sum;
}
console.log(sum(1,2,10));
最后可得:
13```
5.立即执行函数表达式是什么?有什么作用?
function say(){
console.log("hello");
}
say();```
上面的函数必须通过``say()``调用后才可以执行,``function say(){}``只是声明这个函数,并没有执行函数。
我们可以通过对整个函数加小括号来使函数声明变成一个表达式,从而立即执行:
(function say(){
console.log("hello");
})();
或
(function say(){
console.log("hello");
}());
虽然是一个表达式,但是是包裹在函数中的,此时若在此函数内加上``var i = 100;``也只会在此表达式内生效,对其他表达式不影响。其作用就是包裹一段代码,让这段代码拥有自己的作用域,要注意的是,这是一个表达式,所以不会前置,而且立即执行后,在其他地方也无法调用。
##6.什么是函数的作用域链
首先要明确什么是**作用域**:
作用域就是变量和函数的可访问范围,控制着变量和函数的可见性与生命周期,在JavaScript中变量的作用域有全局作用域和局部作用域。
**作用域链:**
当代码在一个环境中执行时,会创建变量对象的一个作用域链(scope chain,不简称sc)来保证对执行环境**有权**访问的变量和函数的**有序**访问。作用域第一个对象始终是当前执行代码所在环境的变量对象。
function a(x,y){
var b=x+y; return b;
}```
在函数a创建的时候它的作用域链填入全局对象,全局对象中有所有全局变量.
如果执行环境是函数,那么将其活动对象(activation object, AO)作为作用域链第一个对象,第二个对象是包含环境,依次向其父级作用域寻找变量。
function a(x,y){
var b=x+y; return b;
}
var tatal=a(5,10);```
此时 ``var tatal=a(5,10);``的作用域如下:
![](https://img.haomeiwen.com/i2399926/e1d9a55dbe77d77e.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
在函数运行过程中标识符的解析是沿着作用域链一级一级搜索的过程,从第一个对象开始,逐级向后回溯,直到找到同名标识符为止,找到后不再继续遍历,找不到就报错。
***
##代码:
##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('男');
![输出结果](https://img.haomeiwen.com/i2399926/7794d3ef164bb1f1.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
##2.写一个函数,返回参数的平方和
```function sumOfSquares(){
var sum = 0;
for(i=0;i<arguments.length;i++){
sum = sum + arguments[i]*arguments[i];
}
console.log(sum);
return sum;
}
sumOfSquares(2,3,4);
sumOfSquares(1,3);```.
##3.如下代码的输出?为什么
console.log(a);
var a = 1;
console.log(b);```
变量提升:
var a;
console.log(a);//undefined(因为声明了 a 但没有赋值)
a = 1;
console.log(b);//b is not defined(没有声明 b)
4.如下代码的输出,为什么
sayName('world');
sayAge(10);
function sayName(name){
console.log('hello ', name);
}
var sayAge = function(age){
console.log(age);
};```
变量提升:
function sayName(name){
console.log('hello ', name);
}
var sayAge = function(age){
console.log(age); //这是一个函数表达式,不会变量前置。
}
sayName('world');
sayAge(10); ```
所以最后输出:
hello,world
10
5.如下代码的输出?为什么
function fn(){
}
var fn = 3;
console.log(fn);
变量提升:
var fn;
function fn(){
}
fn = 3;
console.log(fn);//3
输出: 3
6.如下代码的输出?为什么
function fn(fn2){
console.log(fn2);
var fn2 = 3;
console.log(fn2);
console.log(fn);
function fn2(){
console.log('fnnn2');
}
}
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);```
输出结果:
7.如下代码的输出?为什么
var fn = 1;
function fn(fn){
console.log(fn);
}
console.log(fn(fn));
变量提升:
var fn;
function fn(fn){
console.log(fn);
}
fn = 1;
console.log(fn(fn));```
经过变量提升后,fn已经不是一个函数了,所以输出``fn is not a function``
##8.如下代码的输出?为什么
``` //作用域
console.log(j);
console.log(i);
for(var i=0; i<10; i++){
var j = 100;
}
console.log(i);
console.log(j);```
变量提升:
var j;
var i;
console.log(j);//undefined
console.log(i);//undefined
for(i = 0; i<10;i++){
j =100;
}
console.log(i);//10
console.log(j);//100
for是表达式,不是函数,没有自己的单独作用域,所以``var j = 100;``和``var i =0;``会被前置。最后得到:
undefined
undefined
10
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
最后得出:
undefined
100
10
10.如下代码的输出?为什么
var say = 0;
(function say(n){
console.log(n);//10
if(n<3) return;
say(n-1);//9,8,7,6,5,4,3,2
}( 10 ));
console.log(say);//0
此段代码中的函数为立即执行函数,可以看作是一个表达式,所以不会被前置。若n>3,立刻return输出say