设为首页 加入收藏

TOP

面向对象编程思想(前传)--你必须知道的javascript(一)
2017-10-12 12:16:08 】 浏览:10165
Tags:面向 对象 编程 思想 前传 必须 知道 javascript

在写面向对象编程思想-设计模式中的js部分的时候发现很多基础知识不了解的话,是很难真正理解和读懂js面向对象的代码。为此,在这里先快速补上。然后继续我们的面向对象编程思想-设计模式

什么是鸭子类型

java script是一门典型的动态类型语言,也就弱类型语言。
那什么是鸭子类型:【如果它走起路来像鸭子,叫起来也是鸭子,那么它就是鸭子】

var 鸭子 = {
    走路: function () { },
    咕咕咕: function () { }
}

var 鹦鹉 = {
    走路: function () { },
    咕咕咕: function () { }
}

这只鹦鹉同样有“走路”和“咕咕咕”的方法,那在js的世界里就可以把它当成鸭子。
可以这样调用:

var 鸭子们 = [];
鸭子们.push(鸭子);
鸭子们.push(鹦鹉);

for (var i = 0; i < 鸭子们.length; i++) {
    鸭子们[i].走路();
}

所以js的世界没有抽象和接口,但可以约定“我们都是鸭子”。

java script的面向对象

java script不仅是直译式脚本语言、动态类型、弱类型语言、函数为一等公民的语言,它还是基于原型的面向对象语言。面向对象三大特性:封装、继承、多态,下面我们用js分别实现。

封装

var Person = (function () { 
    var sex = "纯爷们";
    return {
        name: "农码一生",
        getInfo: function () {
            console.log("name:" + this.name + ",sex:" + sex);
        }
    };
})();


虽然老的js语法没有提供private等关键字,但是我们可以利用闭包来实现私有字段,达到封装的目的。

继承

  • 字面量表示:

    var Person = {
    name: "农码一生",
    getName: function () {
        console.log(this.name);
    }
    };
    var obj = Person;
    obj.getName();

  • 函数构造器:

var Person = function () {
    this.name = "农码一生";    
}
Person.prototype.getName = function () {
    console.log(this.name);
}

var obj = function () { };
obj.prototype = new Person();//obj继承于Person

var o = new obj();
o.getName();//直接调用原型中的getName(类似于C#中的调用父类方法)

多态

对于多态,其实上面的鸭子类型已经表现的很清楚了。

var 鸭子们 = [];
鸭子们.push(鸭子);
鸭子们.push(鹦鹉);

for (var i = 0; i < 鸭子们.length; i++) {
    鸭子们[i].走路();//对于鹦鹉来说,它可能是跳着走。对于鸭子来说,它可能左右摇摆着走。这就是多态的表现。
}

对于鹦鹉来说,它可能是跳着走。对于鸭子来说,它可能左右摇摆着走。这就是多态的表现。

原型

什么是原型?在js中是没有类的,那它怎么创建对象。在C#中我们可以通过new关键字实例化一个对象,在js中我们用new关键字构造一个原型对象。C#中一切对象继承于Object,js中一切对象的原型是Object。

var Person = function () {
    this.name = "农码一生";
    this.sex = "纯爷们";
};
console.log(Person.prototype);


我们很多时候给一个对象添加方法的时候就是写在原型上,这是为什么?直接写在对象里会有问题吗?下面我们试试:

var Person = function () {
    this.name = "农码一生";
    this.sex = "纯爷们";
    this.getInfo = function () {
        console.log("name:" + this.name + ",sex:" + this.sex);
    }
};


好像并看不出什么问题。其实不然...

我们发现,每次构造出来的对象中的方法都会去开辟一个空间。但是对象的方法都是一样的,完全没有必要。 我们可以把方法放入原型。

这样一来,不过我们构造多少对象,其方法都是公用的(单例的)。
可是为什么会这样呢?
首先,想想原型这个词,很形象,原本的模型。我们来看一个继承的例子:

var Person = function () {
    this.name = "农码一生";
    this.sex = "纯爷们";
    this.getInfo = function () {
        console.log("name:" + this.name + ",sex:" + this.sex);
    }
};
var Student = function () { };
Student.prototype = new Person();//继承
var s1 = new Student();
var s2 = new Student();
console.log(s1.getInfo === s2.getInfo);


虽然getInfo在Person里面是直接实现的,但是到了Student的原型(prototype)里面就是一个Person对象的单例了。也就是说无论构造多少个Student对象其中的getInfo方法都是同一个。
但是,构造多个Person就有多个getInfo方法。所以,我们应该把getInfo方法放入Person的原型中。

var Person = function () {
    this.name = "农码一生";
    this.sex = "纯爷们";   
};
Person.prototype.getInfo = function () {
    console.log("name:" + this.name + ",sex:" + this.sex);
};

我们仔细推敲下这句话“把getInfo方法放入Person的原型中”,Person的原型是Object,那也就是说getInfo方法放到Object里面去了?
是的,不信请看:

如果原型和原型的原型都实现了同样的方法呢?我们来猜猜下面会打印哪个版本

var Person = function () {
    this.name = "农码一生"; 
};
var Student = function () { }; 
Student.prototype = new Person();//继承
var stu = new Student();

Student.prototype.getName = function () {
    console.log("我的名字:" + this.name);
}
Person.prototype.getName = function () {
    console.log("My name is:&
首页 上一页 1 2 下一页 尾页 1/2/2
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇Java基础——枚举详解 下一篇lua继承

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目