Javascript OOP之面向对象

面向对象程序设计(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; // 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

静态成员

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; // undefined p1.id; // 123 p1.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属性可以取得函数调用的实参个数,可以利用这一点模拟方法的重载。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wzxszf.html