JavaScript 核心篇筆記


//===============================
//ASI機制
var a = 1
;(function() {
    console.log(a);
})()

var a = 1
var b = a
(a + b).toString()   //Uncaught TypeError: a is not a function


33. 未定義的物件屬性預設值檢查
當要檢查全域的物件屬性時,用console.log(window.a);
因為假設直接用console.log(a);  因為屬性不存在,會發生錯誤,導致後面的程式碼都無法執行。

34.物件的參考特性


//IIFE 立即涵式

(function() {
    console.log('立即涵式');
})();

//1.匿名涵式可立刻執行
//2.無法在涵式外被再次執行


//匿名函式也可以傳遞參數
(function(where) { //將參數的變數寫進()
    var Ming = '小明';
    var where;
    console.log(Ming + where);
}('在台北'));  //透過後面的小括號傳遞變數

//匿名涵式本身是表達式,可以回傳值 return
var whereMing = (function(where) { //將參數的變數寫進()
      return where;
}('小明在哪裡'));  //透過後面的小括號傳遞變數
console.log(whereMing);


//匿名涵式傳遞變數的手法
//1.定義一個空物件變數a
var a = {};
(function(b) { //傳入可改名的參數b
   b.person = '小明';  //建立一個物件屬性值
})(a)  //將a物件變數當作參數傳入
;(function(c) {
    console.log(c.person);
})(a)  //可以將a物件傳入


//參數
//涵式內因為hosting的關係,涵式會被提升到最前面; 後面帶入的a變數就變成了function a
function functionA(a) {
            function a() {

            }
            console.log(a);
            var a;
            console.log(a);
            a = '杰倫';
            console.log(a);
        }
        functionA('小明');

結果如下:
ƒ a(){
     
    }
 ƒ a(){
     
    }
 杰倫


    //參數的名稱d,c,b,a,與傳入的值a,b,c名稱可以是不同
    //傳入的參數如果不足,則顯示undefined
function  callMore(dcba) {
            console.log(dcba);
        }
        var a='a'b='b'c='c';
        callMore(abc);

//傳入的參數如果是物件,仍然是有傳參考的特性
   function callObject(obj) {
            obj.name = '大雄家'//改變物件屬性的值為大雄家
        }
        var family = {
            'name' : '小明家'
        }
        callObject(family); //傳入family物件
        console.log(family);

結果: {name: "大雄家"}
許多程式碼規範都建議不要去調整屬性的參數

//參數傳入匿名涵式
function functionA(fn) {
            fn('小明'); //匿名涵式的參數'小明'會傳遞到呼叫的外層a
        }
        functionA(function(a){  //參數傳入一個匿名涵式
            console.log(a);
        });

結果: 小明

 //也可以另外寫一個涵數當成呼叫的變數帶入
  function callSomeone(namea){
            console.log(name + '您好' + a);
        }
        function functionA(fn) {
           fn('小明'1); //匿名涵式的參數'小明'會傳遞到呼叫的外層a
        }
        functionA(callSomeone);


 //同上,此即 回呼涵式 callback

var callSomeone = function (ab) {  //A 將涵式獨立出來
            console.log(a + b)
        }

        function functionB(fnb) {
            fn('Hi,我是實際帶入的參數'1);   //B 執行涵式
        }
        //原本參數帶入涵式 
        functionB(function(a){ console.log(a)});  
        //改成將涵式另外寫並賦於變數--A 另外將涵式獨立出來
        functionB(callSomeone);  //此為涵式表達式, 不會在此執行涵式,
而是在B中執行


arguments 自動帶入參數
agruments 是類陣列,只能用for loop 將參數帶出,不可用其他foreach方法

function someArg(a) { //目前只定義一個參數名稱
            //console.log(a, arguments);
            for(var index=0index<arguments.lengthindex++) {
                console.log(arguments[index]); // 結果: 1,2,3,'4'
            }
        }
        someArg(1,2,3,'4');

   //=======================================
  //閉包 closure
var MingMoney = storeMoney(); //擁有屬於自己開戶的1000存款 ->stpreMoney()是一個可以回傳值得涵式表達式
       console.log(MingMoney(100));  //第一次存入100 傳入參數100  ->1100
       console.log(MingMoney(100));  //第二次存入100 傳入參數100->1200
       console.log(MingMoney(100));  //第三次存入100 傳入參數100 ->1300

       //杰倫開戶
        var JayMoney = storeMoney(); //擁有屬於自己開戶的1000存款 
        console.log(JayMoney(1000));
        console.log(JayMoney(1000));
        console.log(JayMoney(1000));


 //申論題=======================================
        //--依順序取出陣列的值

function arrFunction() {
            var arr = []; 
            for(var i = 0i < 3i++ ) {
                arr.push(function() {
                    console.log(i);
                });
            }
            console.log('i'i); //for 迴圈的結果
            return arr;
        }
        var fn = arrFunction();
        fn[0]();
        fn[1]();
        fn[2]();
        //這樣的結果3個都是3;因為閉包的參數是由外層傳入,所以會取得外層for迴圈執行完的結果 3

 //解決方式2.用匿名涵式限制作用域====================

function arrFunction() {
            var arr = [];

            for (var i = 0i < 3i++) {
                (function (j) {   //使用匿名涵數限制作用域,定義參數名稱
                    arr.push(function () {
                        console.log(j);
                    });

                })(i);//將參數傳入
            }
            console.log('i'i);
            return arr;
        }
        var fn = arrFunction();
        fn[0]();
        fn[1]();
        fn[2]();
        //結果 -> 正確取出 0,1,2

//解決方式3.用ES6的 let 定義變數====================
function arrFunction() {
            var arr = []; 
            for(let i = 0i < 3i++ ) { //用 let 宣告變數,作用域只在for迴圈內
                arr.push(function() {
                    console.log(i);
                });
            }
            //console.log('i', i); //已經無法取得for 迴圈內的變數
            return arr;
        }
        var fn = arrFunction();
        fn[0]();
        fn[1]();
        fn[2]();

//閉包--在涵式裡面定義另一個涵數,裡面的涵式取用外層涵數的變數
// 函式工廠
// 私有方法
function storeMoney(initValue) {    //存錢的function工廠
    var money = initValue || 1000;  //宣告變數money, 初始值為帶進的參數或1000
    return {                        //可以同時執行多種方法; 回傳物件; 
        increase: function(price) {  //增加錢的私有方法
            money += price;
        },
        decrease: function(price) {  //減少錢的私有方法
            money -= price;
        },
        value: function () {         //回傳錢的方法
            return money;
        }
    }
}
var MingMoney = storeMoney(800);  //建立一個小明的涵式工廠
MingMoney.increase(200);          //小明的存錢工廠的存錢私有方法
MingMoney.increase(1000);         //小明的存錢工廠存錢私有方法
MingMoney.decrease(300);          //小明的存錢工廠領錢私有方法
console.log(MingMoney.value());

var JayMoney = storeMoney();         //也可以建立別的涵式工廠 JayMoney
JayMoney.increase(200);
console.log(JayMoney.value());