面向对象一

一、构造函数

       1、构造函数是一个模板。优势:可复用

            构造函数的作用 : 初始化由new创建出来的对象.

            如果一个函数跟new一起使用,此时成为构造函数。就是一个普通函数,任何函数都可以作为构造函数。
            构造函数,是一种函数,主要用来在创建对象时对 对象 进行初始化(即为对象成员变量赋初始值),并且总是与new运算符一起使用。
       2、new 运算符
             new运算符创建一个新对象。关键字new后跟随一个函数调用。
            这里的函数称做:构造函数(constructor),构造函数用以初始化一个新创建的对象。
            new的作用:创建一个新对象(实例)(空对象).
     *注:这个对象可以是用户自定义的,也可以是系统自带的*
       3、 创建对象步骤
              ①new 申请内存, 创建对象
              ②将新对象的引用赋值给 this (obj = this)
              ③调用构造函数,利用 this.成员=值 来给对象添加成员(当然,如果有其他的代码也会执行)
              ④ 返回新对象
       4、构造函数调用说明
             ①先创建对象再调用构造函数
             ②new用来创建对象,原型确定
             ③构造函数用来初始化这个对象
             ④构造函数会自动返回这个新对象
                 构造函数调用和普通的函数调用以及方法调用的不同主要体现在:
                 ①参数处理:没有形参,可以省略实参列表和圆括号。②this指向。③返回值

             ⑤新创建的空对象继承自构造函数的prototype属性
             ⑥对象在被创建的那一刻原型就定下来了。
       5、构造函数返回值
             a. 如果显式地使用return返回一个对象,那么这个对象就会代替新创建的对象被返回
             b. 如果使用return但没有指定返回值或者返回一个原始值,那么此时将会忽略返回

       6、方法放在构造函数中的缺点浪费内存

             构造函数中的属性和方法,会在调用的时候被处理,即会消耗内存。
             new 出来的对象,都是一个单独副本。 new 一个对象就占用一份内存,new 多少对象就占用多少份内存。
             对于构造函数中的方法来说,每个对象的方法都是相同的(或者说应该是被共享的)
      原则:将公共的属性和方法放到 prototype 中。

        7、  构造函数使用注意点

              ①构造函数的名字一般以大写字母开头(推荐)使用new创建一个新对象。

                  ③如果想让创建出来的对象具有某些属性,需要在函数内部通过。this.属性名=值来设置。

             ④构造函数不需要返回值,会默认返回一个对象。

二、原型(prototype)

       原型的说明:

       只要是函数就有 prototype 属性,即函数的原型属性;

       函数的原型属性(prototype)的是 对象类型;

      由 构造函数 创建出来的对象,会默认链接到其构造函数的这个属性(prototype)上;

      构造函数的 prototype 属性的作用就是:实现数据共享

      实例:由构造函数创建出来的对象.  对象:泛指javascript中的复杂数据类型.

      prototype与_proto_相同点和不同点:
     
相同点:1.这两个都是属性,储存的是对象的引用
                    2.这两个属性的值就是同一个对象。
     不同点:1.站在不同的角度去看待这两个属性
                       prototype是站在构造函数的角度;__proto__是站在对象的角度
                   2.__proto__是非标准属性
      原型属性和原型对象:
      是同一个东西;只是站在不同角度去看到这一个东西,对它的不同叫法;目的是为了更加准确地让我们知道指的是谁;原型属性是站在构造函数的角度去看待;原型对象是站在对象的角度看。

三、获取对象的类型

        为什么要获取对象的类型?

        因为一个方法里面可以根据参数类型的不同实现不同的功能。

        一般情况下,使用构造函数的名字描述一个对象的类型。因此,获取对象的类型转化为获取构造函数的名字。

        获取对象 p  的类型,只需要能获取到 "Person" 就获取到类型了。
方式:1 name(兼容性)。2 字符串截取。3 正则表达式。

四、constructor 构造函数/构造器

        任何一个函数的原型默认情况下,都有一个 constructor,这个属性 默认 就指向了 构造函数。

       为什么通过对象p就能够放到 constructor 这个属性?
        1、 constructor 是谁提供的? Person.prototype      2、 属性搜索原则 console.log(p.constructor);
        访问到 constructor 有以下几种方式:
              ① Person.prototype.constructor
              ② p.constructor//此方法是通过属性搜索原则在原型中搜索到的
              ③ p.__proto__.constructor
         属性搜索原则:
              ① 先在对象本身找,有没有该属性,如果有直接返回,如果没有
              ② 在原型对象中查找,如果有直接返回,如果没有
              ③ 就在原型对象的原型对象中查找
              ④ 如果最后也没有找到,此时,结果就是:undefined。

             ⑴每个对象都有一个constructor属性。  ⑵ constructor描述的是对象的构造函数。

            ⑶ p.constructor === Person 结果为true。⑷ 对象的constructor属性是由构造函数的prototype提供的。

       属性修改和读取的区别:
              获取操作:遵循属性查找原则。
              ⑵赋值操作:(只与当前对象有关)。只会操作对象本身,如果对象中没有该属性则创建该属性,并赋值;        如果对象中有,则修改。

五、面向对象

         面向对象语言:c++系的语言:c++/c#/java/object-c/swift
         javascript是一门弱类型的语言:1.javascript中是有类型的2.不受类型的约束
         强类型:变量的类型是不可变的。

        使用 typeof 运算符:无法准确获取对象的类型。

       面向对象的三大特征:封装、继承、多态。

        封装:包装/包裹,将复杂的代码逻辑包裹起来,将简单的东西暴露(留)在外面。
        函数是对具体过程的封装;对象是对行为和数据的封装。

        继承:自己没有,别人有,拿过来让其成为自己的或者自己可以用的。子类可以使用从父类继承的属性和方法。
                   即:让某个类型的对象获得另一个类型的对象的属性的方法。
        继承的方式:1.原型继承   2.混入继承(对象o继承其他的对象o1,o2....)

                  原型继承:

                     为什么将属性和方法放到对象的原型中就能实现继承?
    对象 继承自 原型对象,是对象和原型对象之间的关系。

                    给对象的原型对象添加的任何属性和方法,对象都可以直接拿过来使用。
                    给原型中添加属性:
        1 利用对象的动态特性    添加属性和方法

             对象的动态特性:
              var obj = {};
              obj.name = "jack";
              console.log(obj.name);
              obj.age = 18;
              console.log(obj.age);
              Person.prototype.sayHi = function() {
                      alert("你好");
              };
              Person.prototype.coding = function() {
                      alert("hello world");
              };
             // Person.prototype......
             var p = new Person();
        2 覆盖原型对象               添加属性和方法

            覆盖原型对象:
             var obj = {
                            // 如果对类型要求不严格,那么可以省略,但是,如果对类型的要求严格,此时,需要手动添加一                                  个。属性:constructor,并指向其构造函数
                              constructor: Person,
                              name: "rose",
                              age: 18,
                              sayHi: function() {
                                        alert("where is jack");
                              }
              };
             Person.prototype = obj;
             //Person.prototype = {
                       constructor: Person,
                       name: "rose",
                       age: 18,
                       sayHi: function() {
                                  alert("where is jack");
                       }
              };//
              var p = new Person();
              var t = getType(p.constructor);
              console.log(t);
              function getType(fn) {
                     return (typeof fn !== "function") ? undefined :  (fn.name || /function (.+)\(/.exec(fn + "")[1]);
              }
        3 混入式继承                   添加属性和方法

           混入式继承 :
           Person.prototype.extend = function(obj) {
                    for(var k in obj) {
                            this[k] = obj[k];   // 谁调用这个方法,this 就是谁
                    }
           };
          var o = {
                    name: "rose",
                    age: 18,
                    sayHi: function() {
                              alert("where is jack");
                    }
          };
           // 这是在给原型对象添加属性和方法
            Person.prototype.extend(o);
            var p = new Person();
          // 这是给对象p本身添加属性和方法
            p.extend({
                   name: "rose",
                   age: 18,
                   sayHi: function() {
                              alert("where is jack");
                    }
           });
         以上两种调用方式的区别:
                   如果是共有的属性和方法,就使用原型来调用 extend 添加属性或者方法
                   如果是某个对象特有的属性或者方法,直接使用对象来调用 extend
         var p1 = new Person();

         经典继承:

                 新对象 = Object.create(被继承的对象);// o1 继承自 o2 ,o2被继承。var o1 = Object.create(o2);

                 Object.create的作用:1 创建新对象。2 新对象继承自参数对象。
          var o1;
          var o2 = {
                 name: "张三",
                 age: 19
           };
            // o1 继承了 o2 中的属性和方法,是放在o1的原型中的。
           o1 = Object.create(o2); console.log(o1);
          目的:Object.create 存在兼容性问题,解决兼容性问题
          实现兼容的方式:
                    1 直接在Object对象中修改
                    2 写一个新函数 判断是否支持这个方法,如果支持就拿来用,如不过不支持,就自己实现。
                  var o1;
                  var o2 = {
                         name: "张三",
                         age: 19
                  };
                // 方式一
               // 判断是否支持这个方法
                 if(!Object.create) {
                           // 不支持
                        Object.create = function(obj) {
                                           function F() {}
                                           F.prototype = obj;
                                           var f = new F();
                                           return f;

                        };
                 }
                 var o1 = Object.create(o2);
                  // o1 继承自 o2, 是放在 o1 的原型对象中
                  // 1、 如何创建一个对象?
                  // var o = new Object(); (不能这么直接创建一个Object类型的对象)
                             // function F() {}
                             // var o = new F();
                 // 2、 o2中的属性要放到 o 的原型对象中的去
                             // o.__proto__ 不能这么做
                             // F.prototype = o2;

                方式二 :(推荐使用)

                 function create(obj) {
                           // 1 、判断是否支持Object.create
                             if("create" in Object) {
                                                // 1.1 支持
                                      return Object.create(obj);
                             }
                            function F() {}
                            F.prototype = obj;
                            return new F();
               }
              var o2 = {
                    n: 1,
     m: 2
              };
              var o1 = create(o2);

         多态:(基于强类型,js中没有这个特征)把不同的子类对象都当作父类来看,可以屏蔽不同子类对象之间的差                      异,写出通用的代码,做出通用的编程,适应需求的不断变化。
继承总结:
结论

        1、 只有函数才会有 prototype,所有的函数都有一个prototype属性(一些内置的方法没有,例:                      function  toString())。
        2 、只要是对象就有 __proto__。
        3 、构造函数.prototype 跟 对象.__proto__ 就是同一个东西。
        4、 对象 继承自 原型对象。
        5、 构造函数的prototype 是一个对象类型。
        6、 默认情况下,对象的原型对象是一个具有:constructor属性的对象。
        7、 构造函数.prototype 默认继承自 Object.prototype。

        8、当函数被创建的时候,prototype属性会自动创建和初始化。
       function Person() {}
       var p = new Person();
        console.log(Person.prototype.__proto__ === Object.prototype);
      // Object 是一个函数,函数也是对象

     继承的实现过程:
1 、要创建对象就要有构造函数 (前提:要实现继承)
var o = {};
o.__proto__ === Object.prototype
① __proto__ 非标准的属性,不能用在实际的开发环境中② 所有的对象就都会有这个属性或者是方法
functioin F() {}
F.prototype = 参数;
var f = new F();
2 、如何让f继承自另外一个对象?
前提:f 默认就会继承自 F.prototype 
如果不知道如何让f继承自另外一个对象,只需要改变 默认原型对象的指向即可 F.prototype = 另外一个对象

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值