/*P28-函数-表达式
//函数表达式,不加(),打印出本体(定义)。
function add(a,b){
    return a+b;
}
console.log(add);
/** //下面就是函数add的定义,本体。
 ƒ add(a,b){
    return a+b;
}
*/
/** */

/*
//可以把add函数本体赋值给另一个变量,产生一个同样功能的函数
var plus = add;
var res = plus(5,6);
console.log(res);//11
/*VH:这里额外增加一个点,plus.name
1.所有的都是对象,对象有属性
2.变量有2中,字面变量和引用变量
3.函数对象等是引用变量,add函数本体被plus引用,名字也是原来add的。
*/
/*
console.log('plus().name:'+plus.name);//add

//也可以在函数定义的时候,就直接赋值给一个变量
var multiply = function multiple(a,b){
    console.log(multiple);//标记86
    return a*b;
    //此处开始不要写代码,不会执行!!!
}
console.log(multiply(6,2));//标记90
/** */

/*
//标记86:其实就是index.js:86,怕代码增加会乱,所以手工添加标记在语句末尾
ƒ multiple(a,b){
    console.log(multiple);
    return a*b;
    //此处开始不要写代码,不会执行!!!
}

//标记90:
12

//标记86:又来一遍
ƒ multiple(a,b){
    console.log(multiple);
    return a*b;
    //此处开始不要写代码,不会执行!!!
}
*/

/**VH:增加一点知识:

 //1.定义时直接赋值给变量,那么函数外部无法访问这个函数名的变量,函数内部可以访问。
 //2.定义时直接赋值给变量,那么函数可以没名字,叫匿名函数(不方便后期调试),效果和1一样。

console.log(multiply(6,2));//12
//console.log(multiple(6,2));//Uncaught ReferenceError: multiple is not defined

console.log(multiply);//标记98
//console.log(multiple);//标记99
/*
//第一句标记98的结果:
ƒ multiple(a,b){
    return a*b;
}
//第二句标记99的结果:
Uncaught ReferenceError: multiple is not defined

//注意:参考标记86的结果,函数内部是可以访问multiple的值,外部无法访问。
*/

/*VH:增加一点知识 
1.如果正常定义函数,函数内外都可以访问以函数名的这个变量。
2.复制上面的一句话:定义时直接赋值给变量,那么函数外部无法访问这个函数名的变量,函数内部可以访问。
3.如果var getName= function getName(){}这样重名来定义函数并复制给重名变量。
实现定义并赋值给变量,但是实现正常定义函数的作用。其实多此一举!!!
*/

/*正常定义一个函数:
function getName(){
    console.log('里面打印getName:'+getName);
}
//调用函数:
getName();
console.log('外面打印getName:'+getName)
/*109
里面打印getName:function getName(){
    console.log('里面打印getName:'+getName);
}
112
外面打印getName:function getName(){
    console.log('里面打印getName:'+getName);
}
*/
/** */

/*## 测试这个重新声明函数的问题 */
/*### 函数外部,重新给函数名变量赋值
console.clear();
//var testName = 2;//这里如果不赋值,那么下面这个打印也是函数体,函数提升。如果赋值,那么后面打印都是2(包含最后getTestName),直到testName重新赋值。
console.log(testName);
function testName(){
    console.log('testName()内部打印')
}
var getTestName = testName;
console.log(testName);//testName()函数的定义

var testName;
console.log(testName);//testName()函数的定义,只声明不会改变值(是不是因为提升的原因呢?)
testName = '我是testName的新值';
console.log(testName);//我是testName的新值
console.log(getTestName);//testName()函数的定义,并没有因为testName变量重新赋值而销毁
/** */

//### 函数内部,重新给函数名变量赋值
/*第一步:写函数,内部打印自己
console.clear();

function testName2(){
    console.log('testName2()内部打印');
    console.log(testName2);
}
testName2();
    /*
        index.js:126 testName2()内部打印
        index.js:128 ƒ testName2(){
            console.log('testName2()内部打印');
            console.log(testName2);
        }
     */

/**/

/*第二步:用var声明并赋值
function testName2(){
    console.log('testName2()内部打印');
    var testName2='我是testName2的新值';
    console.log(testName2);
}
testName2();
    /*
    index.js:123 testName2()内部打印
    index.js:125 我是testName2的新值
    */
/**/

/*第三步:不用var声明,并赋值
function testName2(){
    console.log('testName2()内部打印');
     testName2='我是testName2的新值';
    console.log(testName2);
}
testName2();
    /*
    index.js:145 testName2()内部打印
    index.js:147 我是testName2的新值
    */
/**/

/*第四步:用var声明,并不赋值
//var声明后,导致testName2重新生成值为undefined
//正常来说,重新var一个变量不赋值,不改变原值。
function testName2(){
    console.log('testName2()内部打印');
    var testName2;
    console.log(testName2);
}
testName2();
    /*
    index.js:111 已清除控制台
    index.js:158 testName2()内部打印
    index.js:160 undefined
    */
/**/

/*第五步:不用var声明,并不赋值s
//毫无作用,与第一步相同
function testName2(){
    console.log('testName2()内部打印');
     testName2;
    console.log(testName2);
}
testName2();
    /*
    index.js:172 testName2()内部打印
    index.js:174 ƒ testName2(){
        console.log('testName2()内部打印');//
        testName2;
        console.log(testName2);
        }
    */
/**/

/*# 访问域外变量*/

/*## 变量作用域*/
/*### 变量作用域-只用{var声明},没有形成域
//只用{},没有形成域,{var var1}外部可访问var1这个变量
hello=5
var hello2 = 52
{
    world = 6
    var world2 =62
    console.log(hello);//5
    console.log(hello2);//52
}
console.log(world);//6
console.log(world2);//62
/**/

/*### 变量作用域-只用{let声明},没有形成域
//只用{},没有形成域,{let var1}外部可访问var1这个变量
hello=5
let hello2 = 52
{
    world = 6
    let world2 =62
    console.log(hello);//5
    console.log(hello2);//52
}
console.log(world);//6
console.log(world2);//62
/**/

/*### 变量作用域-使用函数(1)-运行函数
//函数样式的{}代码块,形成域
//正常的函数样式的代码块形成了域var局部,不带var是全局

hello=5
var hello2 = 52

function testAccessVaribles(){
    world = 6
    var world2 =62
    console.log(hello);//5
    console.log(hello2);//52
}
testAccessVaribles()
console.log(world);//6
console.log(world2);//Uncaught ReferenceError: world2 is not defined
/**/
/*### 变量作用域-使用函数(2)-不运行函数
//函数样式的{}代码块,形成域
//正常的函数样式的代码块形成了域var局部,不带var是全局
//再加一句(比上个例子),不运行函数,无法访问其内部全局变量,因为没有运行就没有声明啊

hello=5
var hello2 = 52

function testAccessVaribles(){
    world = 6
    var world2 =62
    console.log(hello);//5
    console.log(hello2);//52
}
//testAccessVaribles()
console.log(world);//Uncaught ReferenceError: world2 is not defined
/**/

/*## 特殊情况:函数和函数名的变量
/*### 样式一:正常声明的函数
//1.函数内直接访问是外部(与函数自己同名的)变量值
//2.函数内访问window.函数同名变量,是外部变量值
function getOutVarValue(){
    console.log('getOutVarValue:'+getOutVarValue);//标记1
    console.log('window.getOutVarValue:'+window.getOutVarValue);//标记2
}
var vendor = getOutVarValue;
var getOutVarValue = '我是getOutVarValue的新值';
vendor();//我是getOutVarValue的新值
/*
//标记1
getOutVarValue:我是getOutVarValue的新值
//标记2
window.getOutVarValue:我是getOutVarValue的新值
*/
/**/

/*### 样式2:声明函数并赋值给变量的
//1.函数内部直接访问是函数体
//2.函数内部访问window.函数同名变量,是外部同名变量值
var vendor = function getOutVarValue(){
    console.log(getOutVarValue);//标记1
    console.log('window.getOutVarValue:'+window.getOutVarValue);//标记2
}
var getOutVarValue = '我是getOutVarValue的新值';
vendor();
/*
//标记1
ƒ getOutVarValue(){
    console.log(getOutVarValue);
    console.log('window.getOutVarValue:'+window.getOutVarValue);
}
//标记2
window.getOutVarValue:我是getOutVarValue的新值
*/
/**/

/*测试提升问题*/
/*## 声明变量一定用var,let等关键字么?
        //不用关键字,只写名字没用。
        test;      
        console.log(test);//Uncaught ReferenceError: test is not defined
        /**/

        /*## 声明变量一定用var,let等关键字么?
        //不用关键字,且赋值可以使用
        test2='我是test2';//我是test2
        console.log(test2);
        /**/

        /*## 不用var,放在使用它语句后面,均不能提升
        //赋值或者不赋值,提示referenceError,引用错误
             console.log(test)//test is not defined
             test;
             test = 1;
             //var test;
        /**/

        /*## 用var:提示undefined,说明已经声明
        //var test提升了。
            console.log(test)//defined
             var test;
        /**/

        /*## 用var且赋值:提示undefined,说明已经声明
        //var test提升了。但是赋值在原位置。
            console.log(test)//defined
             var test=2;
        /**/

        /*# 总结:*/

        /*## 提升
        ### 变量提升
        以下写法都会提升(调用的时候,不会提示referenceError,如果未赋值仅提示undefined):
        var var2;
        var var2 = 2;(值2不会提升,仅var2变量提升)
        以下写法可用,不提升,但不能放在调用后面
        var2 = 2;(不能放在调用后面)

        /*### 函数提升
        //调用语句在前或在后都可以

        testRenewName();//第一次声明testRenewName()
        function testRenewName(){
            console.log('第一次声明testRenewName()');
        }
        testRenewName();//第一次声明testRenewName()
        /**/

        /*## 重新声明:
        /*### 变量
        var var3 = 3;
        var var3;//不会改变var3的值。变量提升
        但是在函数中操作要注意(搜索‘第四步’看实例):
        /*
        function testName2(){
        console.log('testName2()内部打印');
        var testName2;//造成下面语句提示undefined
        console.log(testName2);//undefined
        }
        testName2();
        */

        /*### 函数
        重名声明,最后一个为准,而且函数都会提升。

        testRenewName();//第二次声明testRenewName()
        function testRenewName(){
            console.log('第一次声明testRenewName()');
        }
        function testRenewName(){
            console.log('第二次声明testRenewName()');
        }
        testRenewName();//第二次声明testRenewName()
        */
        /**/

        /*## 域外访问
        /*### 正常
        //1.可以访问上一个域声明的变量
        //2.在任意域不用关键字,(前面说了,不加关键字只有赋值才有用)变成全局变量

        //### 函数情况特别
        //#### 正常声明函数(不赋值给其他变量),
            //1.函数内直接访问是外部(与函数自己同名的)变量值
            //2.函数内访问window.函数同名变量,是外部变量值
            //3.估计是全局变量,影响内部变量值,不再是函数体
        //#### 声明且赋值给变量
            //1.函数内部直接访问是函数体
            //2.函数内部访问window.函数同名变量,是外部同名变量值
        /**/

        /*## 类似于本篇的测试文档如何使用失效语句,方便后续测试*/
        //1.测试时每一个关键改动,尽量对应一份完整代码,
        //2.上面说的意思是,把改动的记录保留下来,容易分析
        //3.在一份代码上改动测试,当时知道怎么回事,以后就不容易明白了。

        //格式如下,原理是无论前面几个/ * ,遇到* /就是结束。
        /*标题 //这里末尾增加【* /】,下面的代码语句就可以运行。
        代码语句
            /*
            运行打印结果
            */
        /**/  //这里有一对,表示小节结束!
        /**/


扫一扫 手机查看

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注