Javascript面向对象
2016-10-21 本文已影响60人
JackGood
在简书上看到了关于Javascript面向对象的一些文章,突然也想写一点自己的见解。
按人们认识客观世界的系统思维方式,采用基于对象(实体)的概念建立模型,模拟客观世界分析、设计、实现软件的办法
- 为什么要面相对象?
- 首先要了解什么是面向对象,面向对象有哪些特性。我在网上查到关于面相对象现在还没有统一的概念,如果没有统一的概念,我就先随便找个差不多的概念吧。如上,简单的说就是一切都是对象,什么是对象,对象就是对现实世界的抽象。
- 面相对象有什么特性,我在百度百科上找到几个,然后展开来说。
- 对象唯一性:对象是对现实世界的抽象,现实世界每样东西都是唯一的,所以对象也是唯一的。
- 抽象性:对象是对现实世界的抽象,比如说我们抽象人的概念,每个人都有姓名,性别,年龄等等,但是每个人又有不通的性格,然后我们把他抽象了出来,这就是抽象性
- 继承性:还是人的概念,我们抽象的东西为了实现能够多次的复用,我们一类具有相同属性的东西抽离出来,用于继承这样就能实现代码最大程度上的精简,并且富有逻辑,人类社会不就是这样的么,小明和小红的孩子身上会有小红和小明身上的一些特质,当然,他们的孩子身上也会有,一些小红和小明身上没有的特质。正式因为有这个特性,社会才会进步。
- 多态性:还是用人来举例子,每个人都有不同的名字,我叫每个人,每个人都会回答给我不一样的名字,但是我用了同样的方法去提问,这就是多态性,相同的方法,在不通的对象上体现出来的结果也是不同的。
Javascript如何实现面向对象,要讲Javascript面向对象之前首先要讲一下下面这些神奇的东西。
-
this:对于Javascript来说,一切都是function,那么this的作用域就只是在function里面。这个其实很好理解,但是如果不实际操作那就不一定了,用代码说话。
var name = "ben"; //ben作用域是this.Window function persion() { alert(this.name); //benalert(name); //benthis.name = "jill";//ben function showAge() { var age = 25; alert(this.name);//jill alert(this.age); //undifine 作用域是 //**this.window, age 的作用域在showAge这个方法中** } showAge(); } alert(name);//ben alert(this.name);//ben persion();
* **prototype**:这个东西太他妈重要了,要是不知道的话,别逼我骂人。
//首先说明原型
//这里先借用一个例子
//来自
//http://www.ruanyifeng.com/blog/2011/06/designing_ideas_of_inheritance_mechanism_in_javascript.html
function DOG(name) {
this.name = name;
this.species = '犬科';
}
var dogA = new DOG('大毛');
var dogB = new DOG('二毛');
dogA.species = '猫科';
alert(dogB.species); //示犬科",不受dogA的影响
//下面是原型
function DOG(name) {
this.name = name;
}
DOG.prototype = {species: '犬科'};
var dogB = new DOG('二毛');
alert(dogA.species); // 犬科
alert(dogpecies); // 犬科
//下面是借用原型的实现
function Persion(name, age) {
this.myName = name;
this.myAge = age;
}
persion.prototype = {
showName: function () {
alert(this.myName);
},
showAge: function () {
alert(this.myAge);
}
}
//这样一个人就抽象好了
var jack = new Persion("jack", 25);
var shell = new Persion("shell", 25);
jack.showName(); //jack
shell.showName();//shell
* **constructor**
```javascript
//其实就是一只构造函数
function Persion(name, age) {
this.myName = name;
this.myAge = age;
}
Persion.prototype.showName = function () {
alert(this.myName);
};
alert(Persion.constructor);
var jack = new Persion("jack", 25);
alert(jack.constructor);
//但是constructor是会被覆盖的
function Persion2(name, age) {
this.myName = name;
this.myAge = age;
}
Persion2.prototype = {
showName: function () {
alert(this.myName)
}
}
alert(Persion2.constructor);
var rose = new Persion("rose", 25);
alert(rose.constructor);
//所以如果要用,并不安全,但是我们也要把他给考虑进去
```
* **call/apply**
```javascript
//这个玩意儿相当的重要,重要到无法代替。
//例子还是要举起来
function Persion(name, age) {
this.name = name;
this.age = age;
}
function Student(name, age, school) {
Persion.call(this, name, age, school)
this.school = school;
}
Student.prototype = {
showName: function () {
alert(this.name);
},
showSchool: function () {
alert(this.school);
}
}
var jack = new Student("Jack", "24", "Jialidun");
jack.showName(); // Jack
jack.showSchool();//Jialidun
```
* **arguments**
```
//这个玩意给我们提供了太多的方便,难以言喻。
function Persion(name, age) {
this.name = name;
this.age = age;
}
Persion.prototype = {
setSkills: function () {
for (var item in arguments) {
alert(arguments[item]);
}
}
}
var jack = new Persion("Jack", "24");
jack.setSkills("java", "javascript", "css", "Node.js");
//这个例子充分表明了这个家伙是干什么用的。
```
####基本概念讲完了,下面讲几个我见到过在项目里面做继承的几个示范:
---
* **第一个示范**
/**
* 实现继承类
* @private _object
* */
function _object (o) {
function F() {
};
F.prototype = o;
return new F();
}
/**
*
* 实现继承
* @method inherit
* @private
* @param {Object} subType 子类
* @param {Object} superType 超类
* */
function inherit (subType, superType) {
var p = _object(superType.prototype);
p.constructor = subType;
subType.prototype = p;
}
function Persion(name,age){
this.name = name;
this.age = age;
}
Persion.prototype = {
showName:function(){
alert(this.name);
},
showAge:function(){
alert(this.age);
}
}
function Student(name,age,school){
Persion.call(this,name,age);
this.school = school;
}
inherit(Student,Persion);
Student.prototype.showSchool = function(){
alert(this.school);
}
var jack = new Student("Jack",25,"jialidun");
jack.showName();
jack.showSchool();
* **第二个示范**
function Persion(name,age){
this.name = name;
this.age = age;
}
Persion.prototype = {
showName:function(){
alert(this.name);
},
showAge:function(){
alert(this.age);
}
}
function Student(name,age,school){
Persion.call(this,name,age);
this.school = school;
}
Student.prototype = new Persion(); //这块累赘了
//你知道如果这块不这样,像下面那样
//Student.prototype 和 Persion.prototype 就将是绑定死的
//意思就是如果你改变Student.prototype中的东西
//Persion.prototype也会变,很危险
//孩子怎么能影响父亲呢,大逆不道不是
//Student.prototype = Persion.prototype
Student.prototype.showSchool = function(){
alert(this.school);
}
var jack = new Student("Jack",25,"jialidun");
jack.showName();
jack.showSchool();
* **第三个示范**这个例子来自 [Leaflet](http://leafletjs.com/reference.html)
/*
* L.Class powers the OOP facilities of the library.
* Thanks to John Resig and Dean Edwards for inspiration!
*/
L = {};
L.Util ={
extend: function (dest) {
var i, j, len, src;
for (j = 1, len = arguments.length; j < len; j++) {
src = arguments[j];
for (i in src) {
dest[i] = src[i];
}
}
return dest;
},
// create an object from a given prototype
create: Object.create || (function () {
function F() {}
return function (proto) {
F.prototype = proto;
return new F();
};
})()}
L.Class = function () {};
L.Class.extend = function (props) {
// extended class with the new prototype
var NewClass = function () {
// call the constructor
if (this.initialize) {
this.initialize.apply(this, arguments);
}
// call all constructor hooks
this.callInitHooks();
};
var parentProto = NewClass.__super__ = this.prototype;
var proto = L.Util.create(parentProto);
proto.constructor = NewClass;
NewClass.prototype = proto;
// inherit parent's statics
for (var i in this) {
if (this.hasOwnProperty(i) && i !== 'prototype') {
NewClass[i] = this[i];
}
}
// mix static properties into the class
if (props.statics) {
L.Util.extend(NewClass, props.statics);
delete props.statics;
}
// mix includes into the prototype
if (props.includes) {
L.Util.extend.apply(null, [proto].concat(props.includes));
delete props.includes;
}
// merge options
if (proto.options) {
props.options = L.Util.extend(L.Util.create(proto.options), props.options);
}
// mix given properties into the prototype
L.Util.extend(proto, props);
proto._initHooks = [];
// add method for calling all hooks
proto.callInitHooks = function () {
if (this._initHooksCalled) { return; }
if (parentProto.callInitHooks) {
parentProto.callInitHooks.call(this);
}
this._initHooksCalled = true;
for (var i = 0, len = proto._initHooks.length; i < len; i++) {
proto._initHooks[i].call(this);
}
};
return NewClass;
};
// method for adding properties to prototype
L.Class.include = function (props) {
L.Util.extend(this.prototype, props);
};
// merge new default options to the Class
L.Class.mergeOptions = function (options) {
L.Util.extend(this.prototype.options, options);
};
// add a constructor hook
L.Class.addInitHook = function (fn) { // (Function) || (String, args...)
var args = Array.prototype.slice.call(arguments, 1);
var init = typeof fn === 'function' ? fn : function () {
this[fn].apply(this, args);
};
this.prototype._initHooks = this.prototype._initHooks || [];
this.prototype._initHooks.push(init);
};
//现在开始使用了
Persion = L.Class.extend({
options:{
name:"",
sex:"",
age:""
},
initialize:function(options){
this.name = options.name;
this.sex = options.sex;
this.age = options.age;
},
showName:function(){
alert(this.name);
}
});
Student = Persion.extend({
options:{
name:"",
sex:"",
age:"",
school:"",
score:""
},
initialize:function(options){
Persion.prototype.initialize.call(this, options);
this.school = options.school;
this.score = options.score;
},
showSchool:function(){
alert(this.school);
}
})
var jack = new Student({
name:"jack",
sex:"man",
age:"25",
school:"Beijing University",
score:"A++"
});
jack.showSchool();
这个继承有点长,但是很用,很有启发。简单写了一下用法,但是不全。
>name:Jack
>QQ:84201088
>blog:[http://gdyblog.com](http://gdyblog.com)