函数的优点
- 封装 (把函数保存起来) 2.复用 3.延迟执行 ;
//第一版本
var a = 10;
var b = 20;
var c = 30;
console.log(a+b+c); // 一旦通过浏览器打开 代码就立刻执行
//第二版本 函数优化版本
function add() {
var total = 0;
for (var i = 0; i < arguments.length; i++) {
total += arguments[i];
}
//console.log(total)
return total;
}
// 不想让add 里的代码 在打开浏览器的时候立刻执行
// 通过事件来延迟执行 函数里的代码 ;
var a = 10;
var b = 20;
var c = 30;
var res = add(a, b, c);
console.log(res);//执行60
函数的预解析
预解析 :js内部在执行js之前会把js解释一遍 然后再执行 ;
1.变量预解析 (变量提升);
1.1变量
console.log(a); // 单独打印会报错
console.log(a); // 报错? 不会报错 结果是undefined
var a = 10;
解析上面的代码执行等于变量提升,声明前置了,变量一旦被声明 那么这个变量的声明在js解释阶段会提升到最前面。
var a;//把a的声明提升到最前面
console.log(a);
a = 10; //// a的赋值没有被提升 声明前置
总结 : 变量声明时候,会把变量声明提升到代码最前面;打印变量会得到undefined ; 声明前置是系统内置的,会自动去重排代码顺序 ;
2.函数的预解析 (声明前置);
函数定义有两种 声名式 赋值式
console.log(fn);//fn 函数
function fn(){ // 会提升
console.log("fn");
}
console.log(fn); // fn 函数
var fn = "123"; // 会提升 同时这边fn函数有赋值
console.log(fn); // 123;
在js里 函数被称为最高级 函数优先级更高
函数内部的提升
1.函数内部的变量提升
function fn(){
console.log(a);
var a = 10;
}
fn();//undefined 变量提升了 变量值没有提前。
- 函数内部的函数声明提升;
function fn(){
console.log("fn");
test();
function test(){
console.log("test");
}
}
fn();//执行 fn
test
3.函数和变量同时提升
//预解析前
function fn(){
console.log(a);
var a = 20;
console.log(a);
function a(){ //会提升到最前
console.log("a函数");
}
console.log(a);
}
fn();
//预解析后
function fn(){
function a(){ //会提升到最前
console.log("a函数");
}
console.log(a);//执行a函数
var a = 20;
console.log(a);//执行20
console.log(a);//执行20
}
fn();//执行结果ƒ a(){
console.log("a函数");
}
10
10
4.函数参数和变量提升
// 变量的提升 不会影响 传入的参数的值;赋值后会修改变量
function fn(a){
console.log(a);
var a = 10;
console.log(a);
}
fn(2);//结果 2
10
5.函数的提升:会影响到参数的传入的值;
//预解析前
function fn(a){
console.log(a); // a 的打印结果是??
function a(){
console.log("a函数");
}
}
fn(2);//ƒ a(){
console.log("a函数");
}
//预解析后
function fn(a){
function a(){
console.log("a函数");
}
console.log(a); // a 的打印结果是?
}
fn(2);//打印结果是:ƒ a(){
console.log("a函数");
}
- 变量提升的一个bug 大坑 记住!!!
console.log(a); // a 是啥? 1. undefined 2.报错
// 结果是 undefined 有点不符合逻辑
if(false){
var a = 10;
}
console.log(a);//单独的这个是报错
函数内部的提升 :1.变量;2.参数; 3. 函数;
提升预解析中的提升,函数的优先级始终比变量和参数的优先级更高
注意声名式函数式函数提前,赋值式函数是属于变量提前。
function fn(){
console.log(a) ; // undefined
var a = 10;
console.log(a); // 10
// 注意赋值式函数是一个变量的提升
var a = function(){
console.log("a")
}
console.log(a); //函数
}
fn();//执行结果 undefined
10
ƒ (){
console.log("a")
}
function fn(){
console.log(a) ; // 函数
var a = 10;
console.log(a); // 10
function a(){ //声名式函数提前了
console.log("a");
}
console.log(a); //10
}
fn();//执行结果 ƒ a(){
console.log("a");
}
10
10
函数的作用域
作用域: 一个变量或者是一个函数的使用范围 ;
1.全局作用域 (js里全局内置的变量是window)
console.log(window); //系统内置的全局对象 注意不是windows, windows是系统
var a=10; console.log(window.a)//一般情况下 都会省略window全局变量
// 全局作用域 :就是在全局范围内都可以访问的区域;
function fn(){
console.log("fn");
}
console.log(fn);
//console.log(window.fn);
- 局部作用域(函数作用域)(一个函数包裹的区域);
function fn1(){
var a = 10;
}
fn1();
function fn2(){
console.log(a);//这里的a也是在fn1函数外面 不在fn1函数内,不起作用
}
fn2();//报错
总结:局部作用域,变量只在函数大括号包裹的内部才有作用。
局部作用域的访问规则
1.局部可以访问到全局的内容
var a = 10;
function fn(){
console.log(a);
}
fn();//执行结果 10 自己没有找上层全局作用域
- 如果函数有嵌套关系 变量访问会逐层向上查找,如果当前作用域有改变量会先用当前作用域的
var a = 10;//自己当前作用域有改变量就执行不到全局
function fn(){
var a = 20;//自己有变量值就用优先用自己的
console.log(a);
}
fn();//执行结果 20
var a = 10;
console.log(a);
//全局作用域
function fn1(){
// fn1 的作用域
var a = 20;
function fn2(){
// fn2的作用域
var a = 30;
console.log(a);
}
fn2();
}
fn1();//执行结果 10
30
总结:嵌套作用域访问规则
- 变量就近原则
- 逐层向上查找(作用域是由小的到大的作用域查找) ,都找不到就会报错。
- 注意:访问一定不能向下查找。