摘要:類的繼承建立繼承關系修改的指向調用父類方法調用父類的構造器調用父類上的方法封裝命名空間是沒有命名空間的,因此可以用對象模擬。參考資料面向對象
面向對象程序設計(Object-oriented programming,OOP)是一種程序設計范型,同時也是一種程序開發(fā)的方法。對象指的是類的實例。它將對象作為程序的基本單元,將程序和數(shù)據(jù)封裝其中,以提高軟件的重用性、靈活性和擴展性?!S基百科
一般面向對象包含:繼承,封裝,多態(tài),抽象
對象形式的繼承 淺拷貝var Person = { name: "allin", age: 18, address: { home: "home", office: "office", } sclools: ["x","z"], }; var programer = { language: "js", }; function extend(p, c){ var c = c || {}; for( var prop in p){ c[prop] = p[prop]; } } extend(Person, programer); programer.name; // allin programer.address.home; // home programer.address.home = "house"; //house Person.address.home; // house
從上面的結果看出,淺拷貝的缺陷在于修改了子對象中引用類型的值,會影響到父對象中的值,因為在淺拷貝中對引用類型的拷貝只是拷貝了地址,指向了內存中同一個副本。
深拷貝function extendDeeply(p, c){ var c = c || {}; for (var prop in p){ if(typeof p[prop] === "object"){ c[prop] = (p[prop].constructor === Array)?[]:{}; extendDeeply(p[prop], c[prop]); }else{ c[prop] = p[prop]; } } }
利用遞歸進行深拷貝,這樣子對象的修改就不會影響到父對象。
extendDeeply(Person, programer); programer.address.home = "allin"; Person.address.home; // home利用call和apply繼承
function Parent(){ this.name = "abc"; this.address = {home: "home"}; } function Child(){ Parent.call(this); this.language = "js"; }ES5中的Object.create()
var p = { name : "allin"}; var obj = Object.create(o); obj.name; // allin
Object.create()作為new操作符的替代方案是ES5之后才出來的。我們也可以自己模擬該方法:
//模擬Object.create()方法 function myCreate(o){ function F(){}; F.prototype = o; o = new F(); return o; } var p = { name : "allin"}; var obj = myCreate(o); obj.name; // allin
目前,各大瀏覽器的最新版本(包括IE9)都部署了這個方法。如果遇到老式瀏覽器,可以用下面的代碼自行部署。
if (!Object.create) { Object.create = function (o) { function F() {} F.prototype = o; return new F(); }; }類的繼承 Object.create()
function Person(name, age){} Person.prototype.headCount = 1; Person.prototype.eat = function(){ console.log("eating..."); } function Programmer(name, age, title){} Programmer.prototype = Object.create(Person.prototype); //建立繼承關系 Programmer.prototype.constructor = Programmer; // 修改constructor的指向調用父類方法
function Person(name, age){ this.name = name; this.age = age; } Person.prototype.headCount = 1; Person.prototype.eat = function(){ console.log("eating..."); } function Programmer(name, age, title){ Person.apply(this, arguments); // 調用父類的構造器 } Programmer.prototype = Object.create(Person.prototype); Programmer.prototype.constructor = Programmer; Programmer.prototype.language = "js"; Programmer.prototype.work = function(){ console.log("i am working code in "+ this.language); Person.prototype.eat.apply(this, arguments); // 調用父類上的方法 }封裝 命名空間
js是沒有命名空間的,因此可以用對象模擬。
var app = {}; // 命名空間app //模塊1 app.module1 = { name: "allin", f: function(){ console.log("hi robot"); } }; app.module1.name; // "allin" app.module1.f(); // hi robot靜態(tài)成員
function Person(name){ var age = 100; this.name = name; } //靜態(tài)成員 Person.walk = function(){ console.log("static"); }; Person.walk(); // static私有與公有
function Person(id){ // 私有屬性與方法 var name = "allin"; var work = function(){ console.log(this.id); }; //公有屬性與方法 this.id = id; this.say = function(){ console.log("say hello"); work.call(this); }; }; var p1 = new Person(123); p1.name; // undefined p1.id; // 123 p1.say(); // say hello 123模塊化
var moduleA; moduleA = function() { var prop = 1; function func() {} return { func: func, prop: prop }; }(); // 立即執(zhí)行匿名函數(shù)
prop,func 不會被泄露到全局作用域?;蛘吡硪环N寫法,使用 new
moduleA = new function() { var prop = 1; function func() {} this.func = func; this.prop = prop; }多態(tài) 模擬方法重載
arguments屬性可以取得函數(shù)調用的實參個數(shù),可以利用這一點模擬方法的重載。
function demo(a, b ){ console.log(demo.length); // 得到形參個數(shù) console.log(arguments.length); //得到實參個數(shù) console.log(arguments[0]); // 第一個實參 4 console.log(arguments[1]); // 第二個實參 5 } demo(4, 5, 6);
//實現(xiàn)可變長度實參的相加 function add(){ var total = 0; for( var i = arguments.length - 1; i >= 0; i--){ total += arguments[i]; } return total; } console.log(add(1)); // 1 console.log(add(1, 2, 3)); // 7 // 參數(shù)不同的情況 function fontSize(){ var ele = document.getElementById("js"); if(arguments.length == 0){ return ele.style.fontSize; }else{ ele.style.fontSize = arguments[0]; } } fontSize(18); console.log(fontSize()); // 類型不同的情況 function setting(){ var ele = document.getElementById("js"); if(typeof arguments[0] === "object"){ for(var p in arguments[0]){ ele.style[p] = arguments[0][p]; } }else{ ele.style.fontSize = arguments[0]; ele.style.backgroundColor = arguments[1]; } } setting(18, "red"); setting({fontSize:20, backgroundColor: "green"});方法重寫
function F(){} var f = new F(); F.prototype.run = function(){ console.log("F"); } f.run(); // F f.run = function(){ console.log("fff"); } f.run(); // fff抽象類
在構造器中 throw new Error(""); 拋異常。這樣防止這個類被直接調用。
function DetectorBase() { throw new Error("Abstract class can not be invoked directly!"); } DetectorBase.prototype.detect = function() { console.log("Detection starting..."); }; DetectorBase.prototype.stop = function() { console.log("Detection stopped."); }; DetectorBase.prototype.init = function() { throw new Error("Error"); }; // var d = new DetectorBase();// Uncaught Error: Abstract class can not be invoked directly! function LinkDetector() {} LinkDetector.prototype = Object.create(DetectorBase.prototype); LinkDetector.prototype.constructor = LinkDetector; var l = new LinkDetector(); console.log(l); //LinkDetector {}__proto__: LinkDetector l.detect(); //Detection starting... l.init(); //Uncaught Error: Error參考資料
JavaScript 面向對象
文章版權歸作者所有,未經(jīng)允許請勿轉載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉載請注明本文地址:http://www.ezyhdfw.cn/yun/90832.html
摘要:了解面向對象編程之前,首先要了解的執(zhí)行順序。的解析過程分為兩個階段預處理階段與執(zhí)行期。在執(zhí)行階段的執(zhí)行上下文對象由賦值為指向對應函數(shù) 了解js面向對象編程之前,首先要了解js的執(zhí)行順序。js的解析過程分為兩個階段:預處理階段與執(zhí)行期。 預處理階段 在預處理階段,js會首先創(chuàng)建一個執(zhí)行上下文對象(Execute Context,然后掃描聲明式函數(shù)和用var定義的變量,將其加入執(zhí)行上下文環(huán)...
摘要:構造函數(shù)通常首字母大寫,用于區(qū)分普通函數(shù)。這種關系常被稱為原型鏈,它解釋了為何一個對象會擁有定義在其他對象中的屬性和方法。中所有的對象,都有一個屬性,指向實例對象的構造函數(shù)原型由于是個非標準屬性,因此只有和兩個瀏覽器支持,標準方法是。 從這篇文章開始,復習 MDN 中級教程 的內容了,在初級教程中,我和大家分享了一些比較簡單基礎的知識點,并放在我的 【Cute-JavaScript】系...
摘要:在構造函數(shù)中的中定義的屬性和方法,會被創(chuàng)建的對象所繼承下來。從上面的輸出結果看出,指向了其構造函數(shù)的,而本身也是一個對象,其內部也有屬性,其指向的是直到最后指向,這條原型鏈才結束。和都指向,說明原型鏈到終止。 prototype原型對象 每個函數(shù)都有一個默認的prototype屬性,其實際上還是一個對象,如果被用在繼承中,姑且叫做原型對象。 在構造函數(shù)中的prototype中定義的屬性...
摘要:的變量作用域是基于其特有的作用域鏈的。需要注意的是,用創(chuàng)建的函數(shù),其作用域指向全局作用域。所以,有另一種說法認為閉包是由函數(shù)和與其相關的引用環(huán)境組合而成的實體。 作用域 定義 在編程語言中,作用域控制著變量與參數(shù)的可見性及生命周期,它能減少名稱沖突,而且提供了自動內存管理 --javascript 語言精粹 我理解的是,一個變量、函數(shù)或者成員可以在代碼中訪問到的范圍。 js的變量作...
摘要:對構造函數(shù)使用運算符,就能生成實例,并且變量會綁定在實例對象上。這個對象的所有屬性和方法,都會被構造函數(shù)的實例繼承。 對象 對象的含義 所謂對象,就是一種無序的數(shù)據(jù)集合,由若干個鍵值對(key-value)構成。 對象的創(chuàng)建 使用new運算符創(chuàng)建Object var p = new Object(); p.name = Tony; 使用對象字面量的形式 //對象字面量形...
閱讀 2318·2021-10-09 09:41
閱讀 3498·2021-09-13 10:34
閱讀 1991·2019-08-30 12:59
閱讀 616·2019-08-29 17:27
閱讀 1123·2019-08-29 16:07
閱讀 3025·2019-08-29 13:15
閱讀 1378·2019-08-29 13:14
閱讀 1632·2019-08-26 12:18