JS-JavaScript入门小结2

1.函数声明和函数表达式有什么区别

函数声明:

function fn(){
    console.log(n);
  }//函数声明语句之后不加分号
fn()

函数表达式:

var fn = function(n){
    console.log(n);
  };//函数表达式是一个语句,需要加分号
fn(100)

区别:

var f=function g(){
    console.log(g);
  };
f();//【function g(){console.log(g);}】;
typeof g();//g is not defined

函数声明的方式是定义一个函数的时候,实际上是声明了一个变量,在上面例子中就是f,并把函数赋值给这个变量,普通的函数表达式没有创建该变量,就是我们所说的创建了一个匿名函数。
但是如果函数表达式包含名称,也就是说上面的例子g,那么函数的局部作用域将包含该名称,并且把创建的函数绑定在该名称上。
在上面的例子中g变成了函数的局部变量,变量指向函数本身,所以我们调用f的时候会把其本身打印出来,但是g只作为函数的局部变量存在,我们在外部调用g的时候就会报错了。

2.什么是变量的声明前置?什么是函数的声明前置 ?

变量的声明前置:
在JavaScript解析代码的时候,JS会将所有被声明的变量获取,然后再进行一行一行的运行,这样就会使得所有的变量声明都会被前置,变量声明的前置不会将变量的赋值进行前置

console.log(a);// /*变量前置,但结果是undefined,因为只是获取了a的变量
并没有获取到a变量的值*/
var a=100;//给a变量赋值为100
console.log(a);//此时a的值为100

函数的变量前置:
和变量的声明前置一样,函数声明同样会前置,如果我们使用函数表达式那么规则和变量一样,如果我们使用函数声明的方式,那么即使函数写在最后也可以在前面的语句调用,前提是函数声明部分已经下载到本地

g(10);//先调用函数
function g(n){
console.log(n);//不会报错
};//此为函数声明,就算函数声明在调用之后,也可以使用
g(10);
var g=function fn(n){
  console.log(n);//会报错,g is not function;
}//函数表达式,相当于变量一样,只能声明变量g,不会将声明函数提前;
3.arguments 是什么 ?

在JS中,arguments对象是一种比较特别的对象,实际上是当前函数的一个内置属性,arguments对象的长度是有实参个数而不是形参个数决定的,形参是函数内部重新开辟空间储存的变量,但是其与arguments对象内存空间并不重叠,对于arguments和值都存在的情况下,两者是同步的,但是针对其中一个没有值的情况下,对于无值的参数不会同步

function fn(){
console.log(arguments.length)//输出结果为0
arguments[0]=2;
console.log(arguments.length)//输出结果为0,因为其中fn()中并没有值,所以无值的参数并不会同步
}
fn();

当我们无法知道函数中参数的个数的时候,就可以用arguments来实现,比如实现参数不确定下的求和公式

function fn(){
var sum=0;
for(var i=0;i
4.函数的重载怎样实现?

在一般的面向对象的语言中,确定一个函数的手段是靠方法签名—函数名+参数列表,也就是说相同名字的函数参数个数不同或者顺序不同都可以认为是不同的函数,称为函数重载。在JS中,没有函数重载的概念,函数通过名字确定唯一性,参数不同也被认为是相同的函数,后面的覆盖前面的。

function fn(a,b){
  console.log(a+b);
}
function fn(a,b,c){
  console.log(a+b+c);//函数名与前一个函数名相同,所以会覆盖到前一个fn()函数
}
fn(1,2)//此时fn()执行的是第二个函数,所以会显示为NaN

实现函数的重载可以使用arguments,这样就可以改变参数的个数和参数的顺序,来实现函数的重载

function fn(){
var sum=0;
for(var i=0;i
5.立即执行函数表达式是什么?有什么作用?

立即执行函数是指先创建一个匿名函数,然后不传入参数的调用它,一般的立即执行函数的特征为:

(函数定义表达式)函数调用表达式

常见的立即执行函数表达式有:

(function(){...}())
(function(){...})()

作用:
因为在JS中没有私有作用域的概念,如果多人开发的项目上,你在全局或者局部作用域声明了一些变量,可能会被其他人不小心用同名的变量给覆盖掉,使用立即执行函数可以使得它形成一个封装,用匿名函数作为一个容器,容器内部可以访问外部的变量,而外部环境不能访问容器内部的变量,所以(function(){})()内部定义的变量不会和外部的变量发生冲突。

 var name=3;
 (function name(n){alert(n)})(2);//输出2
alert(name);//输出3
6.什么是函数的作用域链?

先观察一下下列代码:

name="Jack";  
function fn1(){  
    var name="Rose"; //在fn1中声明了一个局部变量name为"Jack"
    function fn2(){  
        var name="Alisa"; // /*fn2中定义了一个局部变量,但不会改变外部name变量的值,
                             这个值只会在fn2函数中生效*/
        console.log(name);  //此时输出的就是局部变量name的值“Alisa“
    }  
    function fn3(){  
        console.log(name);  //此时name值获取的为fn1中声明的局部变量”Rose“
    }  
    fn2();// /*执行fn2的执行环境,此时fn2会获取自己上一级的所有对象
                在fn2中获取了fn1中name局部变量的值为Jack,然后执行fn2中的函数*/
   fn3();  // /*执行fn3中的执行环境,此时fn3中没有name变量值,
              他就会向上一级进行获取,上一级没有就会再上一级进行获取,
              直到根级,即Windos
}  
fn1();  

当代码在一个环境中执行时,会创建变量对象的的一个作用域链(scope chain)。作用域链的用途,是保证对执行环境有权访问的所有变量和函数的有序访问。作用域链的前端,始终都是当前执行的代码所在环境的变量对象。如果这个环境是一个函数,则将其活动对象作为变量对象。每一个函数都有自己的执行环境,当执行流进一个函数时,函数环境就会被推入一个环境栈中,而在函数执行之后,栈将其环境弹出,把控制权返回给之前的执行环境,这个栈也就是作用域链

在JS中存在局部变量和全局变量,全局变量作用于全局,局部变量只作用于一个函数内部,用var进行定义,当函数中定义局部变量的时候必须使用var,不使用var的话就会将这个变量设为全局变量,所以在函数内部不使用var定义的话,就默认为全局变量,这样会造成其他函数使用该变量的时候发生错误。

var name="jack";
function fn1(){
  name="Alisa";
  console.log(name);
};
function fn2(){
  console.log(name);
};
fn1();//输出为Alisa
fn2();//输出为Alisa

此文章由饥人谷_李子豪及饥人谷所有

你可能感兴趣的:(JS-JavaScript入门小结2)