zoukankan      html  css  js  c++  java
  • javascript学习五---OOP

    面向对象:JavaScript的所有数据都可以看成对象
    JavaScript的面向对象编程和大多数其他语言如Java、C#的面向对象编程都不太一样。如果你熟悉Java或C#,很好,你一定明白面向对象的两个基本概念:
       面向对象的两个基本概念:
           1、类:类是对象的类型模板,例如,定义Student类来表示学生,类本身是一种类型,Student表示学生类型,但不表示任何具体的某个学生;
           2、实例:实例是根据类创建的对象,例如,根据Student类可以创建出xiaoming、xiaohong、xiaojun等多个实例,每个实例表示一个具体的学生,他们全都属于Student类型。
           所以,类和实例是大多数面向对象编程语言的基本概念。
    
       JavaScript不区分类和实例的概念,而是通过原型(prototype)来实现面向对象编程。
       JavaScript的原型链和Java的Class区别就在,它没有“Class”的概念,所有对象都是实例,所谓继承关系不过是把一个对象的原型指向另一个对象而已。
    
       JS的prototype和__proto__
            一、prototype和__proto__的概念
                prototype是函数的一个属性(每个函数都有一个prototype属性),这个属性是一个指针,指向一个对象。它是显示修改对象的原型的属性。
                __proto__是一个对象拥有的内置属性(请注意:prototype是函数的内置属性,__proto__是对象的内置属性),是JS内部使用寻找原型链的属性
                用chrome和FF都可以访问到对象的__proto__属性,IE不可以。
    
            二、new 的过程
                var Person = function(){};
                var p = new Person();
                new的过程拆分成以下三步:
                (1) var p={}; 也就是说,初始化一个对象p
                (2) p.__proto__ = Person.prototype;
                (3) Person.call(p); 也就是说构造p,也可以称之为初始化p
                关键在于第二步,我们来证明一下:
                var Person = function(){};
                var p = new Person();
                alert(p.__proto__ === Person.prototype);
    
           三、示例
                var Person = function(){};
                Person.prototype.sayName = function() {
                    alert("My Name is Jacky");
                };
                Person.prototype.age = 27;
                var p = new Person();
                p.sayName();
    
            p是一个引用指向Person的对象。我们在Person的原型上定义了一个sayName方法和age属性,当我们执行p.age时,会先在this的内部查找(也就是构造函数内部),如果没有找到然后再沿着原型链向上追溯。
            这里的向上追溯是怎么向上的呢?这里就要使用__proto__属性来链接到原型(也就是Person.prototype)进行查找。最终在原型上找到了age属性
    
    
    
          为了解决从原型对象生成实例的问题,Javascript提供了一个构造函数(Constructor)模式。
          所谓"构造函数",其实就是一个普通函数,但是内部使用了this变量。对构造函数使用new运算符,就能生成实例,并且this变量会绑定在实例对象上。
          案例:
            function Cat(name,color){
                this.name=name;
                this.color=color;
    
              }
              我们现在就可以生成实例对象了。
              var cat1 = new Cat("大毛","黄色");
              var cat2 = new Cat("二毛","黑色");
              alert(cat1.name); // 大毛
              alert(cat1.color); // 黄色
    
                这时cat1和cat2会自动含有一个constructor属性,指向它们的构造函数。
               alert(cat1.constructor == Cat); //true
                alert(cat2.constructor == Cat); //true
          Javascript还提供了一个instanceof运算符,验证原型对象与实例对象之间的关系。
              alert(cat1 instanceof Cat); //true
              alert(cat2 instanceof Cat); //true
    
          五、 Prototype模式
                Javascript规定,每一个构造函数都有一个prototype属性,指向另一个对象。这个对象的所有属性和方法,都会被构造函数的实例继承。
                这意味着,我们可以把那些不变的属性和方法,直接定义在prototype对象上。
                这意味着,我们可以把那些不变的属性和方法,直接定义在prototype对象上。
    
              function Cat(name,color){
                this.name = name;
                this.color = color;
              }
              Cat.prototype.type = "猫科动物";
              Cat.prototype.eat = function(){alert("吃老鼠")};
    
          六、 Prototype模式的验证方法
              6.1 isPrototypeOf()
                这个方法用来判断,某个proptotype对象和某个实例之间的关系。
                  alert(Cat.prototype.isPrototypeOf(cat1)); //true
                  alert(Cat.prototype.isPrototypeOf(cat2)); //true
    
             6.2 hasOwnProperty()
                每个实例对象都有一个hasOwnProperty()方法,用来判断某一个属性到底是本地属性,还是继承自prototype对象的属性。
                  alert(cat1.hasOwnProperty("name")); // true
                  alert(cat1.hasOwnProperty("type")); // false
    
             6.3 in运算符
    
                in运算符可以用来判断,某个实例是否含有某个属性,不管是不是本地属性。
                  alert("name" in cat1); // true
                  alert("type" in cat1); // true
                in运算符还可以用来遍历某个对象的所有属性。
                  for(var prop in cat1) { alert("cat1["+prop+"]="+cat1[prop]); }
    
    
    比如,现在有一个"动物"对象的构造函数。
      function Animal(){
        this.species = "动物";
      }
    
    还有一个"猫"对象的构造函数。
    
      function Cat(name,color){
        this.name = name;
        this.color = color;
      }
    
    怎样才能使"猫"继承"动物"呢?
    一、 构造函数绑定
        第一种方法也是最简单的方法,使用call或apply方法,将父对象的构造函数绑定在子对象上,即在子对象构造函数中加一行:
       function Cat(name,color){
            Animal.apply(this, arguments);
            this.name = name;
            this.color = color;
      }
      var cat1 = new Cat("大毛","黄色");
      alert(cat1.species); // 动物
    
    二、 prototype模式
    
    第二种方法更常见,使用prototype属性。
    如果"猫"的prototype对象,指向一个Animal的实例,那么所有"猫"的实例,就能继承Animal了。
    
      Cat.prototype = new Animal();
      Cat.prototype.constructor = Cat;
      var cat1 = new Cat("大毛","黄色");
      alert(cat1.species); // 动物
    
    任何一个prototype对象都有一个constructor属性,指向它的构造函数。
    
    案例:
    class Student {
        constructor(name) {
            this.name = name;
        }
        hello() {
            console.log('Hello, ' + this.name + '!');
        }
    };
    var xiaoming = new Student('小明');
    xiaoming.hello();
    
    结果:Hello, 小明!
    
    class PrimaryStudent extends Student {
        constructor(name, grade) {
            super(name); // 记得用super调用父类的构造方法!
            this.grade = grade;
        }
        myGrade() {
            alert('I am at grade ' + this.grade);
        }
    };
    var teddy = new PrimaryStudent('teddy','no.1');
    teddy.myGrade();
    
    结果:'I am at grade no.1'
  • 相关阅读:
    luogu P3834 【模板】可持久化线段树 1(主席树) 查询区间 [l, r] 内的第 k 小/大值
    覆盖的面积 HDU
    Picture POJ
    Atlantis HDU
    Transformation HDU
    Tunnel Warfare HDU
    Agri-Net POJ
    Conscription POJ
    Brush (IV) LightOJ
    Throwing Dice LightOJ
  • 原文地址:https://www.cnblogs.com/1314520xh/p/14204019.html
Copyright © 2011-2022 走看看