var a = 1; var b = 2; function c(){} function d(){}
var space = { a: 1, b: 2, c: function () { console.log('我是c'); return this.a; }, d: function () { console.log('我是d'); return this.b; }, }; console.log(space.a); console.log(space.b); console.log(space.c()); console.log(space.d());
這樣就把變量掛載到 space 上了,而不是全局 window 上javascript
function Class() { this.a = 1; this.b = 2; } Class.prototype.c = function () { console.log('我是c'); return this.a; }; Class.prototype.d = function () { console.log('我是d'); return this.b; }; var instance = new Class(); console.log(instance.a); //1 console.log(instance.b); //2 console.log(instance.c()); //我是c //1 console.log(instance.d()); // 我是d //2
面向對象必定程度上解決了命名衝突的問題,可是 js 沒有私有變量,暴露內部變量,外部可有對內部數據進行修改外部能夠修改內部數據css
(function (window) { let a = 1; let b = 2; function c() { console.log('我是c'); return a; } function d() { console.log('我是d'); return b; } window.module = { c:c, d:d, } })(window); //或者 var module = (function(){ let a = 1; ... function c(){ ... } ... return { a:a, c:c } })()
這一方式能夠作到私有變量,模塊的基本寫法,好比 jqueryhtml
(function () { var a = 1; window.module = { c: function () { return a }, } })(); (function (mod) { var b = 2; mod.d = function () { return b } })(window.module) console.log(module.c()); console.log(module.d()); console.log(module);
能夠實現模塊的分離和模塊的繼承,也具備私有變量,還能夠將自執行函數拆分紅多個文件進行加載,可是文件的執行順序有必定的要求,要先聲明對象 module前端
//將上面給module添加功能的函數添加個默認值 (function (mod) { var b = 2; mod.d = function () { return b } })(window.module || {})
能夠將模塊分紅不一樣的文件,同時文件不用再考慮加載順序不對致使 module 不存在的狀況java
(function ($) { var a = 'red'; $('.hello').css({ "background": a }); })(jQuery)
自執行函數jquery
自執行函數中()分組操做符是用來將 function(){}這個函數聲明轉化爲一種能夠執行的表達式,單純的 function(){}不是可執行的表達式,是一個函數聲明
()分組操做符能夠替換爲其餘操做符,好比 '#','+','-','!','void'......等等git
//這樣寫也是能夠的 +function ($) { var a = 'red'; $('.hello').css({ "background": a }); }(jQuery)
function(){}是函數聲明,聲明的是一個匿名函數,而(function(){})()是一個表達式,而 js 在預編譯階段會解釋函數聲明,確會忽略表達式.因此到(function(){})的時候,該表達式會返回一個匿名函數,以後該匿名函數遇到後面的(),便會被執行github
var lis = document.querySelectorAll('li'); for(var i=0;i<5;i++){ lis[i].onclick = function(){ alert(i); //5,5,5,5,5 } } //又是這個經典的題目 //這題最簡單仍是用元素屬性的方式去解決,好比 for(var i=0;i<5;i++){ lis[i].index = i; lis[i].onclick = function(){ alert(this.index); //0,1,2,3,4 } } //還有就是閉包 for(var i=0;i<5;i++){ (function(i){ lis[i].onclick = function(){ alert(i); //0,1,2,3,4 } })(i) } //閉包就是在循環中執行,將i的值保存到當前做用域中,當click綁定的函數觸發時,會優先從離得最近的做用域去拿變量(就近原則) //因此,使用其餘的方式將當前i值保存到本身的做用域中就行 for(var i=0;i<5;i++){ click(i); } function click(i){ lis[i].onclick = function(){ alert(i); //0,1,2,3,4 } } //這其實就跟上面的閉包有些相似了,閉包取i是從上級的匿名函數的做用域中取保存的i,而該方式就是從click函數的做用域中去取i值