zoukankan      html  css  js  c++  java
  • JS中的面向对象

    一、首先创建js对象的四种方式:
    1.普通模式

     var person=new Object();
    person.name="Irving";
    person.age=22;
    person.sayHi=function(){
    alert(this.name);
    }

     但是这样每次去创建一个类的对象相当的麻烦。所以有了下面的集中创建对象的模式。
    2.工厂模式

     function person(name,age){
    var p=new Object();
    p.name=name;
    p.age=age;
    p.sayHi=function(){
    alert(this.name);
    };
    return p;
    }

    这样就创建一一个person类(并不是真正意义上的方法,其实我们能看到,它只不过是一个方法,一个Object的对象的实例而已,里面所谓的属性,只不过是以Object特有的键值对的形式存在)。

     var p1 = person("Irving",22);
    var p2 = person("Irving",26);
    p1.sayHi();
    p2.sayHi();

    这个结果,应该猜都能猜出来。

    3.构造函数模式

     function person(name,age){
    this.name=name;
    this.age=age;
    this.sayHi=function(){
    alert(this.name);};
    }
    var p1 =new person("Irving",22);
    var p2 =new person("Irving",26);
    p1.sayHi();
    p2.sayHi();

    new关键字:

    • 开辟堆空间;
    • 创建对象;
    • 将构造函数作用域赋值给新对象(this就指向了该新对象);
    • 执行构造函数中的代码(为新对象添加属性);
    • 返回新对象

    4.原型模式,其实上面的集中方法都有大家看不到的缺陷。
    每个实例上都有自定义的各个方法对象,这样多个对象调用这个方法的时候就消耗内存资源。我们在想能不能让同一个类的对象都区调用同一个方法对象。这样就不会占用那么多的内存空间。
    好,这个时候prototype的好处就体现了。

    function person(name,age){
    this.name=name;
    this.age=age;
    }
    person.prototype.sayHi=function(){
    alert(this,name);
    }
    var p1 =new person("Irving",22);
    var p2 =new person("Irving",26);
    p1.sayHi();
    p2.sayHi();


    二、继承
    1.方法的继承,首先用原型模式创建一个父类。

     function Person(name,age){
    this.name=name;
    this.age=age;
    }
    Person.prototype.sayHi=function(){
    alert(this,name);
    }

    2.创建子类,

     function Student(){
    }
    Student.prototype=Person.prototype;
    var stu=new Person();

    如何判断stu继承了person?只要stu能点出sayHi这个方法出来就证明stu能够调用这个方法,也就是说继承了这个方法。

    stu.sayHi();很显然的能点出来,运行的话,会弹出undefinde,既然弹出了,就证明方法执行了,方法执行了就证明方法继承过来的,至于弹出的我们下面来解决。//这样子类student就能够继承父类的方法。

    但是这样父类的属性还没有继承过来,这个时候就需要考虑用到apply或者call方法,来改变函数的作用域了。

    我们更改下这个子类的构造函数

     function Student()
    {
    Person.apply(this,["panpan",22])
    }

    这个时候我们在执行sayhi这个方法的时候就会弹出panpan。那这个时候我们的继承就好解决了,我们可以在student这个类中传2个参数,name,age。然后在apply中的第二个参数设置为name和age的数组。  

    function Student(name, age) {
    Person.apply(this, [name, age])
    }

    好吧,我们看下完整的代码。

     function Person(name, age) {
    this.name = name;
    this.age = age;
    }
    Person.prototype.sayHi =function () {
    alert(this.name);
    }
    function Student(name, age) {
    Person.apply(this, [name, age])
    }
    Student.prototype = Person.prototype;
    var stu =new Student("Irving", "23");
    stu.sayHi();

    这样我们的继承问题就解决了。

     Student.prototype = Person.prototype;

    这个代码是把person的原型指针赋给了student的原型,也就是说我们给Student.prototype添加一个属性的时候,父类person也会具有这个属性。

     Student.prototype.eat =function () {
    alert(this.name+"跑步");
    }
    var per =new Person("Irving", 23);
    per.eat();

    但是

     var per =new Person("Irving", 23);
    per.eat();

    这个代码必须放在

     Student.prototype.eat =function () {
    alert(this.name+"我在吃饭");
    }

    之后,因为代码是从上到下执行的。

    在没有给原型指针添加属性方法的时候是没办法访问到的。
    上述的代码也就是说我们在给子类添加方法的时候,我们父类也有了这些方法,但是理论上来说对于继承是不允许这样的。
    那么我们怎么对子类添加方法而不会使父类也拥有这些方法呢。
    我们看一下,stu调用sayHi方法是怎么执行的。

    首先创建一个stu的对象,在栈上保存这个变量stu,在堆上保存new出来的对象,stu这个变量指向堆上对象的地址。当我们调用stu的sayHi方法时,首先会到student这个对象去找方法,找不到这个方法,然后去原型里面去找, 由于这个方法的原型实质上是person类的原型的地址。所有就到person类中区找,找到了就调用这个方法。
    如果我们将子类的原型指向父类的对象呢?

    Student.prototype =new Person();

    这就是所谓的原型继承。

    这里我补充下继承的几种方法,上面的内容涉及到原型继承和类继承(构造函数继承),一般的类继承会使用call\apply函数去尝试绑定一个访问关系,让子类能够访问的父类的实例属性。这里就不多说,下面介绍一种实例继承,一般是用来封装系统对象的,也可以引用到自定义对象。如下:

     function A(){
    this.x =1;
    }
    function B(){
    var aObj =new A();
    aObj.getX =function(){
    alert(aObj.x);
    }
    return aObj;
    }
    var bObj =new B();
    bObj.getX();
  • 相关阅读:
    SpringBoot笔记
    SpringBoot面试篇
    多线程篇
    Tomcat篇
    Redis篇
    Nginx篇
    JVM篇
    MySQL篇
    python ETL工具 pyetl
    python通用数据库操作工具 pydbclib
  • 原文地址:https://www.cnblogs.com/Irving/p/2558658.html
Copyright © 2011-2022 走看看