国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > JavaScript > 正文

Javascript OOP之面向對象

2019-11-20 09:22:25
字體:
來源:轉載
供稿:網友

面向對象程序設計(Object-oriented programming,OOP)是一種程序設計范型,同時也是一種程序開發的方法。對象指的是類的實例。它將對象作為程序的基本單元,將程序和數據封裝其中,以提高軟件的重用性、靈活性和擴展性。――維基百科

一般面向對象包含:繼承,封裝,多態,抽象

對象形式的繼承

淺拷貝

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; // allinprogramer.address.home; // homeprogramer.address.home = 'house'; //housePerson.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//模塊1app.module1 = {  name: 'allin',  f: function(){    console.log('hi robot');  }};app.module1.name; // "allin"app.module1.f(); // hi robot

靜態成員

function Person(name){  var age = 100;  this.name = name;}//靜態成員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; // undefinedp1.id; // 123p1.say(); // say hello 123

模塊化

var moduleA;moduleA = function() {  var prop = 1;  function func() {}  return {    func: func,    prop: prop  };}(); // 立即執行匿名函數

prop,func 不會被泄露到全局作用域。或者另一種寫法,使用 new

moduleA = new function() {  var prop = 1;  function func() {}  this.func = func;  this.prop = prop;}

多態

模擬方法重載

arguments屬性可以取得函數調用的實參個數,可以利用這一點模擬方法的重載。

function demo(a, b ){  console.log(demo.length); // 得到形參個數  console.log(arguments.length); //得到實參個數  console.log(arguments[0]); // 第一個實參 4  console.log(arguments[1]); // 第二個實參 5}demo(4, 5, 6);//實現可變長度實參的相加function add(){  var total = 0;  for( var i = arguments.length - 1; i >= 0; i--){    total += arguments[i];  }  return total;}console.log(add(1)); // 1console.log(add(1, 2, 3)); // 7// 參數不同的情況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(); // Ff.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__: LinkDetectorl.detect(); //Detection starting...l.init(); //Uncaught Error: Error

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 大新县| 高雄县| 鄂托克前旗| 乐清市| 五家渠市| 杂多县| 大安市| 简阳市| 尚志市| 高邮市| 金坛市| 柯坪县| 平山县| 那曲县| 周至县| 凯里市| 蒙城县| 吴忠市| 淄博市| 长寿区| 泉州市| 余干县| 思茅市| 探索| 崇明县| 隆子县| 大宁县| 小金县| 眉山市| 钟山县| 山丹县| 山阳县| 深水埗区| 灌阳县| 永寿县| 长宁区| 三亚市| 安顺市| 大关县| 家居| 元朗区|