JS面向对象的特点
在JS中,有对象,没有类(但有构造函数),因此,有人说JS是“基于对象”而非面向对象,其实JS的面向对象非常灵活,比起静态语言,能达到意想不到的效果。
JS的对象不依赖类而存在,可以直接生成。
var chicken = {leg:2,sing:function(){alert("在下是鸟!");}}; //json格式
JS对象的属性可以任意添加和删除(方法和属性不必严格区分)
var chicken.arm = 2; //添加属性 delete chicken.sing; //删除方法
对象的三大特点:封装,继承,多态
私有属性与封装
//封装 function Dog(){ this.leg = 4; this.bark = function(){ alert("汪汪"); } } var huzi = new Dog(); huzi.bark(); //输出 汪汪 alert(huzi.leg); //输出 4 /* 此处,我们并没有完成面向对象的“封装”,所谓封装:就是要封闭一部分,外界无法访问, 开放一部分,通过开放部分简介访问私有部分。 */ //通过闭包完成私有属性的封装 function Dog(name,feature){ var private = feature; //外界无法直接访问,只能通过对象属性调用 this.leg = 4; this.eat = function(){ return feature; } this.favorite_eat = function(){ feature = "骨头"; } } var dog = new Dog("huzi","吃屎"); alert(dog.name + "喜欢" + dog.eat()); alert(dog.name + "喜欢" + dog.favorite_eat());
详解原型链继承
JS没有类的概念,因此,JS的继承,不是通过类的继承来实现的,而是通过“原型”的概念来完成的。
//创建cat的构造函数 function Cat(){ this.climb = function(){ alert("我会爬树"); } } //创建tiger的构造函数 function Tiger(){ this.bark = function(){ alert("我是百兽之王"); } } //下面让虎继承猫的属性:爬树 Tiger.prototype = new Cat(); var hnhu = new Tiger(); hnhu.climb(); hnhu.valueOf();
老虎是如何爬树和valueOf的呢?
老虎先在自身对象上寻找,没有爬树方法,valueOf()方法,去找原型,原型cat对象上由此方法,得以调用climb()方法,但valueOf()仍没有找到,因此,继续沿着原型查找,找到cat空对象,仍没有valueOf()放法,再找,找到Objecte对象,有valueOf()方法,调用成功。
对象-->原型-->原型的原型-->Object对象-->Null,这样的一条链称为原型链
对象的属性和方法,就是沿着原型链查找和调用的,也就是JS中的原型继承
//给所有对象添加一个方法 Object.prototype.sing = function(){ alert("我会唱歌"); } function Pig(){ this.eat = "10KG"; } var zhu = new Pig(); zhu.sing();
原型冒充及复制继承
JS的语法非常灵活,不仅可以用原型继承,还有其他办法,如:原型冒充或复制继承
//原型冒充 function Cat(leg,tail){ this.leg = leg; this.tail = tail; this.climb = function(){ alert("我会爬树"); } } function Tiger(leg,tail,color){ //把要继承的类的语句,拿来执行一遍 this.parent = Cat; //把父类构造函数引入到一个parent属性上 this.parent.apply(this,arguments); //获取Cat参数 this.color = color; delete this.parent; } var tiger = new Tiger(); tiger.climb();
用Tiger造对象时,用Tiger语句影响一个空对象{ },在此过程中,Tiger影响空对象前,先由Cat函数实施影响,因此,最终得到的对象,是由Cat和Tiger两者共同作用过得对象。
//复制继承 function Cat(leg,tail){ this.leg = leg; this.tail = tail; this.climb = function(){ alert("我会爬树"); } } function Tiger(leg,tail,color){ this.color = color; this.extend = function(parent){ for(var key in parent){ this[key] = parent[key]; } } } var tiger = new Tiger("yellow"); tiger.extend(new Cat(4,1)); tiger.climb();
动态语言谈不上多态
JS谈不上多态,因为即JS就没有限制参数类型
function Dog(){ this.leg = 4; this.bark = null; } function Hashiqi(){ this.bark = function(){ alert("wuwu"); } } function Jingba(){ this.bark = function(){ alert("wuwu"); } } Hashiqi.prototype = Jingba.prototype = new Dog(); var h = new Hashiqi(); var j = new Jingba(); function test(dog){ dog.bark(); } test(h); test(j);
传入不同的狗,叫声也不同
JS面向对象之静态方法
构造函数通过new来制造对象
函数本身也是对象
function Machine(){ this.on = function (){ alert("我可以制作豆浆!"); } } Machine.heat = function(){ alert("加热!"); } var m = new Machine(); //m没有heat方法,就像豆浆机的加热功能不会跑到豆浆里 m.on(); Machine.heat();
heat方法属于函数本身的,和返回的对象没有关系
on要调用,必须要new Machine();得到对象,且由返回对象才能调用
heat方法要调用,不需要new对象,直接用Machie来调用