JavaScript_引用類型

數組

在ECMAScript中數組是很是經常使用的引用類型
ECMAScript所定義的數組和其餘語言中的數組有着很大的區別
數組也是一種對象javascript

建立數組

//方法一
var arr = new Array();

//方法二
var arr1 = [];

特色

  • 數組即一組數據的集合java

  • js數組更加相似java的map容器。長度可變,元素類型任意jquery

  • 數組長度隨時可變!隨時能夠修改!(length屬性)chrome

    var arr1 = [123,324,true,'abc',1,4,5,new Date()];編程

    arr1.length = 5;數組

    console.log( arr1 );
    //log 裏面是傳遞的字符串 , JS引擎默認會調用.toString(); 隱式的調用.瀏覽器

經常使用方法

push、pop
shift、unshift
splice、slice
concat、join、sort、reverse(逆序)閉包

影響原數組
splice()
arr.splice(開始項,[控制幾位數,值]);  //statr ,count ,
var arr = [1,2,3,4,5,6,7];
var zf = arr.splice(3); //控制幾位數, 默認值 :arr.length-1 //包括3 原來項數
console.log( arr ); //[1,2,3]
console.log( zf ); //[4,5,6,7]  //返回值 -- 取出的內容
 

var arr = [1,2,3,4,5,6,7]; 
var zf = arr.splice(3,2);  //截取
console.log( arr ); //[1, 2, 3, 6, 7]
console.log( zf ); //[4,5] 
 

var arr = [1,2,3,4,5,6,7]; 
var t = arr.splice(3,2,'zf','dd'); //替換
console.log( arr ); //[1,2,'zf','dd',6,7]
console.log( t );  //[4,5]
 

var arr = [1,2,3,4,5,6,7]; 
var t = arr.splice(3,0,'zf','dd');  //插入
console.log(arr); //[1,2,3,'zf','dd',4,5,6,7]
console.log( t );  //[]  //若是爲0 ,去除空數組
 

var arr = [1,2,3,4,5,6,7]; 
var 12 = arr.splice(-4); //截取
console.log( arr ); //[1,2,3]
console.log( zf ); //[4,5,6,7]

//
slice(stat,end)  //去出了end-stat 項。 不包括end項。

var zf = arr.sort(function ( a,b ) {  //傳遞匿名函數,經過匿名函數參數判斷大小。
    if( a>b ){
        return 1;
    } else if( a<b ){
        return -1;
    } else {
        return 0;
    }
});
console.log( arr ); //["a", "b", "e", "z"]
console.log( zf );  //["a", "b", "e", "z"]

// 影響原數組
push , pop ,unshift ,shift  ,splice  ,reverse  ,sort
// 未影響 原數組
concat ,slice ,join

ES5數組新特性

位置方法:indexOf lastIndexOf
迭代方法:every filter forEach some map
縮小方法:reduce reduceRightapp

// indexOf();  //查找位置 

var arr = [234,23,45,46,45,645,56];

//1個參數的時候,表示傳值  返回索引位置
var idxVal = arr.indexOf(45);

//2個參數的時候, 第一個表示查詢的值,第二個參數是 傳值,表示起始開始查詢的起始位置
var idxVal = arr.indexOf(2,3);

//查找數組比較的時候 是 "===" 

//找不到返回 -1

//迭代方法

//every : 對於數組每個元素進行一個函數的運行  若是函數都返回true, 最後則返回true。  若是有一個返回false 最後結果則返回false。
// 測試數組的全部元素是否都經過了指定函數的測試 

var arr =  [1,2,3,4,3,2,4,6];

var reslut = arr.every(function ( item,index,array ) {
    
    return item > 0;
    
});

console.log( reslut );  //true



//filter : 對於數組的每個元素進行一個函數的運行  給定的函數執行, 把過濾後的結果返回。

var arr =  [1,2,3,4,3,2,4,6];

var reslut = arr.filter(function ( item,index,array ) {
    
    return item > 2;  //全部大於2 的過濾出來
    
})

console.log( reslut );  //[3, 4, 3, 4, 6]


//forEach : 循環數組每一項,  並執行一個方法
// 方法中的參數:數組成員的值,數組成員的索引,原數組(修改原數組會影響原來遍歷的數組)

var arr =  [1,2,3,4,3,2,4,6];

arr.forEach(function ( item,index,array ) {
    
    console.log( item );
    
});

var arr1 = ['tan', 'cyan', 'pink', 'red'];
arr1.forEach(function ( val, idx, arrs ) {
    
    return 1; // 返回返回並不會影響原數組
    
});
console.log(arr);


//map  : 對於數組的每個元素進行一個函數的運行  能夠通過函數執行完畢   把新的結果返回, 原數組不變。

var arr =  [1,2,3,4,3,2,4,6];

var reslut = arr.map(function ( item,index,array ) {
    
    return item * 3;
    
}); 

console.log( reslut );  //[3, 6, 9, 12, 9, 6, 12, 18]


//some : 對於數組每個元素進行一個函數的運行  若是有一項返回true  最後則返回true  若是每一項都返回false, 最後才返回false。 

var arr =  [1,2,3,4,3,2,4,6];

var reslut = arr.some(function ( item,index,array ) {
    
    return item > 5;  //有一個返回true, 就返回true
    
});

console.log( reslut );  //true

//模擬filter方法
Array.prototype.filter = function ( cb ) {
    
    var reslut = [];
    
    try{
        
        if ( cb && cb.constructor === Function ) {
                
            for ( var i=0; i<this.length; i++ ) {
                
                if ( cb.call(this[i],this[i],i,this) ) {
                    
                    reslut.push(this[i]);
                    
                }
        
            }
            
        }
        
    }catch(e){
        //TODO handle the exception
    }
    
    return reslut ? reslut : '';
    
}

var a = arr.filter(function ( item,index,arr ) {
    
    return item > 2;
    
});
console.log( a );



// 模擬some
Array.prototype.some = function ( fn ) {
    
    try{
        
        if ( fn && fn.constructor === Function ) {
            
            
            for ( var i=0; i<this.length; i++ ) {
                
                // 存在一個函數執行結果 爲true , 返回true
                if ( fn.call(this[i], this[i], i, this) ) {
                    
                    return true;
                    
                }
                
            }
            return false;
        }
        
    }catch(e){
        //TODO handle the exception
    }
    
}

var arr =  [1,2,3,4,3,2,4,6];

// reduce  reduceRight

// 前一個值, 當前值, 索引位置, array 
// 數組中的每一個值(從左到右)開始合併,最終爲一個值。
// 接收一個函數做爲累加器,數組中的每個值(從左到右)開始合併,最終爲一個值。
var reslut = arr.reduce(function ( prev,cur,index,array ) {
    
    return prev + cur;
    
});

console.log( reslut ); //25

// reduceRight 從右開始遍歷
var reslut1 = arr.reduceRight(function ( prev,cur,index,array ) {
    
    return prev + cur;
    
});

console.log(  reslut ); //25

// 獲得接口的對象

var o = (function() {
    var person = {
        name: 'xixi',
        age: 22,
    }
    return {
        sayName: function(k) {
            return person[k];
        },
    }
}());

var person = ['name', 'age'].reduce(function (obj, k) {
//     console.log(obj, k,'--');
    obj[k] = o.sayName(k);
    return obj;
},{});

console.log(person);

數組判斷方法:
Array.isArray();
判斷是否爲數組,若是是,則返回true,不然返回false。dom

var arr = [];
console.log( Array.isArray(arr) );

填充方法:
fill();
實現對數組的填充
參數:接受值,直接填充,若是是函數,也是直接填充

// arr.fill(1);
// arr.fill(function () {
//     return 2;
// });
// arr.fill([1,2,3]);
arr.fill({x: 1});

console.log(arr);

Object

引用類型都是Object類型的實例,Object也是ECMAScript中使用最多的一種類型(就像java.lang.Object同樣,Object類型是全部它的實例的基礎) //全部類的 基礎類。

Object類型的建立方式、使用

對於Object類型應用for in 枚舉循環

Obj每一個實例都具備屬性和方法

Constructor: 保存着用於建立當前對象的函數。(構造函數)

hasOwnProperty(propertyName):用於檢測給定的屬性在當前對象實例中(而不是原型中)是否存在。

isPrototypeOf(Object): 用於檢查傳入的對象是不是另一個對象的原型。

propertyIsEnumerable(propertyName):用於檢查給定的屬性是否可以使用for-in語句來枚舉。

toLocaleString():返回對象的字符串表示。該字符串與執行環境的地區對應.

toString():返回對象的字符串表示。

valueOf():返回對象的字符串、數值或布爾表示。

OBject.prototype.toString()

Object.prototype.toString
做用:根據內部的this返回一個相似於這樣的字符串 [object constructorName]
這個方法有個缺點,不能獲取用戶自定義對象的具體類型.
只能獲取內置對象的類型.
自定義對象類型都返回:[object Object]

console.log(Object.prototype.toString.call([])); // [object Array]
console.log(Object.prototype.toString.call(Array)); // [object Fcuntion]
console.log(Object.prototype.toString.call(new Date())); // [object Date]

// 簡寫方式
console.log(({}).toString.call([])); // [object Array]

toString();

// 字符串  ==> String.prototype.toString();
var a = 't';
console.log(a.toString()); // t
var a = new String(); 
console.log(a.toString()); // 空字符串
var a = new String('string');
console.log(a.toString());   // string

// 數組 ==> Array.prototype.toString();
var b = [1, 2, 3, 4];
console.log(b.toString()); // 1,2,3,4
var b = [];
console.log(b.toString()); // 空字符串
var b = new Array();
console.log(b.toString()); // 空字符串
var b = new Array(3, 5);
console.log(b.toString()); // 3,5


// 對象 ==> Object.prototype.toString();
var c = {};
console.log(c.toString()); // [object Object]

// 函數
console.log(Function.toString()); // function Function() { [native code] }
console.log(Array.toString()); // function Array() { [native code] }
console.log(RegExp.toString()); // function RegExp() { [navtive code] }

關於JSON函數

JSON.parse()

做用:將JSON字符串解析成JavaScirpt值。在解析過程當中,能夠選擇性的修改某些屬性的原始解析值。
參數1:JSON字符串
參數2: reviver 函數,用來轉換解析出的屬性值。(可選參數)
返回值:解析出的一個 Object

console.log(JSON.parse(10));  // 10
console.log(JSON.parse(true)); // true
console.log(JSON.parse('"xixi"')); // xixi
console.log(JSON.parse(null));  // null
console.log(JSON.parse('"undefined"')); // undefined
console.log(JSON.parse("[]")); // []

若是指定了 reviver 函數,解析的出的Object, 解析值自己以及它所包含的全部屬性,會按照必定的順序(從最最裏層的屬性開始,一級級往外,最終到達頂層)分別去調用 指定的reviver 函數。

在調用過程當中,當前屬性所屬的對象會做爲this值,當前屬性名和屬性值會分別做爲第一個參數和第二個參數傳入 reviver 函數中,若是 reviver 函數返回undefeind,則當前屬性會從屬性對象中刪除,若是返回了其它值,則返回的值會成爲當前屬性新的屬性值。
當遍歷到最頂層的值(解析值)時,傳入reviver函數的參數會是空字符串''(由於此時已經沒有真正的屬性)和當前的解析值(有可能已經被修改過),當前的this值會是{"":修改過的解析值},

JSON.parse('{"p": 5}', function (key, val) {

  if(key === '') return val;     // 若是到了最頂層,則直接返回屬性值
    
  return val * 2;
    
});

JSON.stringify();

stringify(value [,replacer, [space]]);
將任意的JavaScript值序列化成JSON字符
參數1:value: 將序列化成JSON字符串的值
參數2:replacer: 可選,若是是一個函數,則在序列化過程當中,被序列化的值的每一個屬性都會通過該函數的轉換和處理。 若是是一個數組,則暴行在這數組中的屬性名纔會被序列化到最終的JSON字符串中。
參數3:space, 指定縮進可通的空白字符串,用於美化輸出。 控制結果字符串裏的間距。

注意:

  • 不可枚舉的屬性會被忽略

  • 非數組對象的屬性不能保證以特定的順序出現的序列化後的字符串中。

  • 布爾值,數字,字符串的包裝對象在序列化過程當中會自動裝換成對應的原始值。

  • undefeind,任意的函數,以及symbol值,在徐淚花過程橫縱揮別忽略(出如今非數組對象的屬性值中時)或者被轉換成null(出如今數組中時)

  • 全部以symbol爲屬性鍵的屬性值都會被徹底忽略掉,即使 replacer參數中強制指定包含了它們

    console.log(JSON.stringify([undefined, Object, Symbol()])); // null, null, null
    console.log(JSON.stringify({x: undefined, y: Object, z: Symbol()})); // {}

Object.create

ES5爲對象提供了一個Object.create();
做用:建立一個類,是一種寄生式繼承。
返回一個類,這個類的原型指向傳遞進來的對象。

建立的實例化對象,構造函數指向的是繼承的對象的類的構造函數。自己沒有原型,能夠經過原型鏈找到繼承的對象類中的原型。具備繼承對象上的屬性以及方法。
所以,建立的實例化對象可使用繼承對象上的屬性和方法。

var Book = function (title, price) {
    
    this.title = title;
    
    this.price = price;
    
}

Book.prototype.sayTitle = function () {
    
    return this.price;
    
}

var book = new Book('one', 10);

// 建立一個繼承類
var NewBook = Object.create(book);

console.log(NewBook.constructor);

var price = NewBook.sayTitle();

console.log(price);

// 模擬 Object.create();
// 寄生式繼承
Object.prototype.create = function ( obj ) {
    
    try{
        
        if ( obj && obj.constructor === Object ) {
            
            function F () {}
            
            F.prototype = obj;
            
            return F;
            
        }
            
        
    }catch(e){
        //TODO handle the exception
    }
    
}

// 建立一個繼承類
var NewBook = Object.create(book);

console.log(NewBook.constructor);

var price = NewBook.sayTitle();

console.log(price);

Object.defineProperty

Object.defineProperty();
直接在一個對象上定義一個新屬性,或者修改一個已經存在的屬性,並返回這個對象。
參數1:須要被設置的對象
參數2:設置的屬性名
參數3:配置項,添加屬性的特性屬性

特性屬性:
value:該屬性值,默認值:undefeind
writable: 能否被修改,默認值:false (不能被修改)
configuarable: 可否經過delete刪除屬性從而從新定義屬性,可以修改屬性的特性,或者可否把屬性修改成訪問屬性。 默認值:false;(不能夠從新定義或刪除)
enumerable: 是否能夠被for-in枚舉。默認值:false

var obj = {};

Object.defineProperty(obj, 'title', {
    
    value: 'tan',
//                writable: true,
    configurable: false,
//                enumerable: true
    
});

delete obj.title;

//            obj.title = 'pink';

//            for ( var i in obj ) {
//                
//                console.log(obj[i]);
//                
//            }

console.log(obj);

特性方法:
set:給屬性提供setter的方法,若是沒有setter則爲undefined。默認值undefiend。
參數:該參數的新值分配給該屬性。默認:undefined

Object.defineProperty(obj, 'title', {
    
    get: function () {
        console.log('get');
        return this._title;
    },
    set: function ( val ) {
        this._title = val;
    }
    
});


obj.title = 'pink';

var t = obj.title;

defineProperties

在一個對象上添加或修改一個或多個自有屬性,並返回該對象。
參數1:表示要被處理的對象
參數2:定義多個屬性特性對象

var obj = {}

Object.defineProperties(obj, {
    
    color: {
        value: 'tan'
    },
    
    names: {
        value: 'zf'
    }
    
});

console.log( obj );

getOwnPropertyNames

Object.getOwnPropertyNames();
返回一個由指定對象的全部自身屬性的屬性名(包括不可枚舉屬性)組成的數組。
參數:須要獲取的對象。

getOwnPropertyDescriptor

Object.getOwnPropertyDescriptor();
指定對象上一個自由屬性對應的屬性描述符。(自由屬性指的直接賦予該對象的屬性,不須要從原型鏈上進行查找的屬性)
參數1: 獲取的對象。
參數2:獲取的屬性值

模擬map

模擬java中的Map

//簡單實現 map

function Map () {
    
    //priveate 的對象來保存  key 和 val
    var obj = {};
    
    // put 方法
    this.put = function ( key,val ) {
        
        
        obj[key] = val;   //把鍵值對 綁定到object上.
        
    }
    
    //得到map 容器的個數
    this.size = function () {
        
        var count = 0;
        
        for ( var i in obj ) {
            
            count++;
            
        }
        
        return count;
        
    }
    
    //根據key  獲得  val
    this.get = function ( key ) {
        
        return obj[key] || (obj[key] === 0) || (obj[key] === false) ? obj[key] : null;
        
    }
    
    // remove 刪除方法
    this.remove = function ( key ) {
        
        if ( obj[key] || obj[key] === 0 || obj[key] === false ) delete obj[key];  
        
    }
    
    //eachMap 遍歷 map 容器的方法
    this.eachMap = function ( cb ) {
        
        if ( cb && cb.constructor === Function ) {
            
            for ( var i in obj ) {
                
                cb.call(this,i,obj[i]);
                
            }
            
        }
        
    }
    
}

var m = new Map();

m.put('01',120);
m.put('02','tan');

//            console.log( m.size() );
//            
//            console.log( m.get('0') );

//            m.remove('01');
//            console.log( m.get('01'),'--' );

m.eachMap(function ( key,val ) {
    
    console.log( key,val,'---' );
    
});

去掉數組的重複項

var arr = [1,2,4,2,3,4,5,546,57,6,5,4,31,57];

//js 對象特性, 數組去重 
// 在 js 對象 中 key 是永遠 不會重複的.


// 1, 把數組轉成一個js的對象
// 2,把數組中的值,變成js 對象當中的key
// 3,把對象再還原成數組

//數組轉對象
var toObject = function ( arr ) {
    
    var reslutObj = {};
    
    for ( var i=0; i<arr.length; i++ ) {
        
        if ( arr ) {
        
            reslutObj[arr[i]] = null; //賦值爲任意值
            
        }
        
    }
    
    return reslutObj;
    
}

//對象轉成數組
var toArray = function ( obj ) {
    
    var reslutArr = [];
    
    for ( var attr in obj ) {
        
        if ( obj.hasOwnProperty(attr) ) {  //判斷是不是自身上面的屬性
            
            reslutArr.push(attr);
            
        }
        
    }
    
    return reslutArr;
    
}

//去掉數組中的重複項
function uniq ( arr ) {
                
    return toArray(toObject(arr));
                
}
    
console.log( uniq(arr) );

其餘引用類型

單體對象(不須要實例化對象,就可使用的方法):

Global對象(全局)這個對象不存在,無形的對象(特別的,特殊的存在)
其內部定義了一些方法和屬性:encodeURI 、encodeURIComponent、decodeURI、decodeURIComponent、eval、parseInt、parseFloat、isNaN(在js 裏面 只有NaN 本身不等於本身自己的)、Escape、 unescape

// encodeURI 、encodeURIComponent、

var uri = 'http://www.baidu.com cn';
var str1 = encodeURI(uri);  //http://www.baidu.com%20cn                  //(url: //不會進行編碼)
var str2 = encodeURIComponent(uri);  //http%3A%2F%2Fwww.baidu.com%20cn  //任何不標準的文字都會進行編碼

console.log( str1 );
console.log( str2 );

// decodeURI、decodeURIComponent、
console.log( decodeURI(str1) );  //  http://www.baidu.com cn
console.log( decodeURIComponent(str2) );  // http://www.baidu.com cn

//eval(string) 方法  無形的javascript 解析器

var str1 = 'var a = 10; var b = 20;';
eval(str1);

console.log( a+b );

//數組字符串  直接使用: eval(strArr);

var arr = '[10,203,345,45,6]';

var evalArr = eval(arr);

console.log( evalArr );

//對象字符串  
var obj = '{name: "123", age: 20}';

var evalObj = eval('(' + obj + ')' );

console.log( evalObj );//Object {name: "123", age: 20}

//escape  unescape  URI 轉碼
var str = '八百米';
var str2 = escape(str); //%u516B%u767E%u7C73

console.log( str2 );

Math對象
內置的Math對象能夠用來處理各類數學運算
能夠直接調用的方法:Math.數學函數(參數)
求隨機數方法:Math.random(),產生 [0,1) 範圍一個任意數

Date對象
獲取當前時間的一系列詳細方法

var date = new Date();

console.log( date.getTime() );     //當前時間的毫秒數

基本包裝類型:Boolean、String、Number

Function類型、RegExp類型

簡單單體和閉包單體

單體(singleton)模式是js中最基本但又最有用的模式之一,它可能比其餘任何模式都經常使用。
這種模式提供了一種將代碼組織爲一個邏輯單元的手段,這個邏輯單元中的代碼能夠經過單一的變量進行訪問。經過確保單體對象只存在一份實例,就能夠確信本身的全部代碼使用的都是一樣的全局資源。

簡單單體

// 簡單單體模式   (只能建立一個實例)//沒法經過new 關鍵字來實例化.
var Singleton = {  //當成模板類 
    attr1: true,
    attr2: 10,
    
    method1: function () {
        
        console.log( this.attr1 );
        
    }
    
}

Singleton.method1();


//劃分命名空間(區分代碼)

閉包單體

//    利用閉包來建立單體  , 閉包主要的目的 , 保護數據

var alogy = {};
alogy.singleton = (function () {
    
    
    //添加私有成員
    
    var a = 100;
    var fn1 = function () {
        
        console.log( a );                            
        
    }
    
    // 塊級做用域裏的執行結果賦值 單體對象
    return {
        attr1: 10,
        attr2: 20,
        method: function () {
            console.log( this.attr1 );
        },
        fn1: fn1
    }
        
        
})();

alogy.singleton.method();
alogy.singleton.fn1();

惰性單體

//惰性單體 (和閉包單體相似)

//經過 一個私有變量來控制是否 實例化對象, 初始化一個 init。

var Ext = {};

Ext.Base = (function () {

//私有變量 控制返回的單體對象
var uniqInstance;  

//須要一個構造器  init 初始化單體對象的方法
function Init () {
    
    //私有成員
    var a1 = 10;
    var a2 = true;
    
    var fun1 = function () {
        
        console.log( a1 );
        
    }
    
    return {
        attr1: a1,
        attr2: a2,
        fun1: fun1
    }
    
}

return {
    
    getInstance: function () {
        
        if ( !uniqInstance ) {  //不存在 ,建立單體實例
            
            uniqInstance = new Init();                    
            
        }
        
        return uniqInstance;
        
    }
    
}

})()

var init = Ext.Base.getInstance();

init.fun1(); //10

分支單體

//分支單體  (判斷程序的分支 - 瀏覽器差別的檢測)
//簡單判斷
var Ext = {};

var def = true; 

Ext.More = (function () {
    
    var ff = {
        attr1: 'ff'
    };
    
    var ie = {
        attr1: 'ie'
    }
    
    return def ? ff : ie;
    
})()

console.log( Ext.More.attr1 ); //ff

簡單鏈式編程實現

簡單鏈式調用。 return this;

//簡單函數鏈式調用 

function Dog () {
    
    this.run = function () {
        
        console.log( 'dog is run...' );
        
        return this;
        
    }
    
    this.eat = function () {
        
        console.log( 'dog is eat...' );
        
        return this;
        
    }
    
    this.slepp = function () {
        
        console.log('dog is sleep');
        
        return this;
        
    }
    
}

var d1 = new Dog();

d1.run().eat().slepp();

模擬jquery底層代碼

//模擬jquery底層鏈式編程
    
// 函數自執行 特色:
// 1: 程序啓動時候   裏面代碼自動執行
// 2: 內部的成員變量  外部沒法訪問 (除了不加var修飾的變量)

//塊級 做用域   

(function ( window,undefined ) {
    
    //$ 最經常使用的對象  返回給外界  //大型程序開發   通常使用 '_'做爲私有的對象
        
    function _$ ( args ) {
        
        // 匹配id 選擇器
        var idSelect = /^\#[\w+]?/;
        
        this.dom;  // 接收所獲得的元素
        
        if ( idSelect.test(args) ) { //匹配成功接收元素  // #div 
            
            this.dom = document.getElementById(arguments[0].substr(1));
        
        } else {
            
            throw new Error('選擇器不正確!');
            
        }
        
    }
    
    //在Function類上 擴展 一個能夠實現 鏈式編程的方法
    Function.prototype.method = function ( methodName,fn ) {  //實現鏈式編程, 方法的名字 和  進行調用的函數是什麼
        
        this.prototype[methodName] = fn;
        
        return this; //鏈式編程
        
    }
    
    // 在 _$ 原型對象上  加一些公共的方法
    _$.prototype = {
        
        constructor: _$,
        
        addEvent: function ( type,cb ) {
            
            //ff chrome
            if ( window.addEventListener ) { 
                
                this.dom.addEventListener(type,cb,false);
                
            //ie
            } else if ( window.attachEvent ) { 
                
                this.dom.attachEvent('on'+type,cb);
                
            }
    
            return this;
            
        },
        
        setStyle: function ( key,val ) {
            
            this.dom.style[key] = val;
            
            return this;
            
        }
        
    }
    
    //window上註冊 一個 全局變量
    window.$ = _$;
    
    //準備方法
    _$.onReady = function ( cb ) {
        
        //1,實例化  _$ 對象 ,註冊到 window上
        window.$ = function ( args ) {
            
            return new _$(args); 
            
        }
        
        //2: 執行傳入的代碼
        cb.call(window);
        
        //3: 實現鏈式編程 
        _$.method('addEvent',function () {}).method('setStyle',function () {});
        
    }
    
})( window )  //程序的入口  window傳入做用域中            



$.onReady(function () {
    
    $('#div')
    .addEvent('click',function () {
        
        console.log('點擊了');
        
    })
    .setStyle('background','pink')
    
});

嚴格模式

嚴格模式是JavaScript中的一種限制性更強的變種方式。
嚴格模式與非嚴格模式能夠共存,能夠逐漸的選擇性加入嚴格模式。

全局做用域

定義變量必須經過var
嚴格模式禁止刪除聲明變量。

delete關鍵字

使用delete刪除一個變量名(而不是屬性名): delete myVariable

'use strict';

delete Object.prototype; // error . 
// 刪除一個不可配置的屬性

函數參數

定義相同名稱的參數
要求參數名惟一。
在正常模式下,最後一個重名參數名諱覆蓋以前的重名參數,以前的參數仍然能夠經過arguments[i]來訪問,還不是徹底沒法訪問。

關鍵字,保留字

使用eval或arguments做爲變量名或函數名

嚴格模式下:
訪問arguments.callee, arguments.caller, anyFunction.caller以及anyFunction.arguments都會拋出異常

禁止使用八進制

瀏覽器都支持以零(0)開頭的八進制語法:0644 == 420 還有 '\045 === '%''
認爲數字的前導零沒有語法意義,可是會改變數字的意義。

eval

嚴格模式下不能向全局做用域下添加變量

在正常模式下,代碼eval('var x;') 會給上層函數或全局引入一個新的變量 x
嚴格模式下,eval爲被運行的代碼建立變量,eval不會影響到名稱映射到外部變量或其它局部變量。

var x = 22;

var evalX = eval("var x = 42; x");

console.log(x === 22);
console.log(evalX === 42);

函數內部this

在正常模式下函數調用,this的值會指向全局對象,在嚴格模式中,this的值會指向undefiend。

當函數經過call和apply調用時,若是傳入的是thisvalue參數是一個null和undefiend除外的原始值(字符串,數字,布爾值),則this的值會成爲那個原始值的對應的包裝對象。若是thisavlue參數的值是undefeind或null,則this的值會指向全局變量。在嚴格模式中,this值就是thisvalue參數的值,沒有任何類型轉換。

this: 僅在this指向本身建立的對象時使用它

arguments

arguments對象屬性不語對應的形參變量同步更新。
非嚴格模式下,修改arugmetns對象中的某個索引屬性的值,和這個屬性對應的形參變量的值也會同時變化。
嚴格模式下,arguments對象會以形參變量的拷貝的形式被建立和初始化。所以arguments對象的改變不會影響形參。

arguments: 老是經過形參的名字獲取函數參數,或者在函數的第一行拷貝arguments

var args = Array.prototype.slice.call(arguments)

with

嚴格模式禁用with。
with問題:塊內的任何變量均可以映射到with傳進來的對象的屬性,也能夠映射到包圍這個塊的做用域內的變量(甚至是全局變量),在運行時纔可以決定:在代碼運行以前沒法獲得。
嚴格模式下,使用with會引發語法錯誤。

var x = 7;
with (obj) {  // 語法錯誤
  // 若是沒有開啓嚴格模式,with中的這個x會指向with上面的那個x,仍是obj.x?
  // 若是不運行代碼,咱們沒法知道,所以,這種代碼讓引擎沒法進行優化,速度也就會變慢。
  x;
}
相關文章
相關標籤/搜索