//===============================
//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(d, c, b, a) {
console.log(d, c, b, a);
}
var a='a', b='b', c='c';
callMore(a, b, c);
//傳入的參數如果是物件,仍然是有傳參考的特性
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(name, a){
console.log(name + '您好' + a);
}
function functionA(fn) {
fn('小明', 1); //匿名涵式的參數'小明'會傳遞到呼叫的外層a
}
functionA(callSomeone);
//同上,此即 回呼涵式 callback
var callSomeone = function (a, b) { //A 將涵式獨立出來
console.log(a + b)
}
function functionB(fn, b) {
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=0; index<arguments.length; index++) {
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 = 0; i < 3; i++ ) {
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 = 0; i < 3; i++) {
(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 = 0; i < 3; i++ ) { //用 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());