zoukankan      html  css  js  c++  java
  • javascript面向对象编程笔记

    对象:一切事物皆是对象。对象是一个整体,对外提供一些操作。比如说一个收音机是一个对象,我们不需要知道它的内部结构是什么,只需要会使用外部的按钮就可以使用收音机。

    面向对象:面向对象语言的标志是他们都有类的概念,通过类可以创建任意多个具有相同属性的方法的对象。任何对象都是某一类事物的实例,简单的说就是使用对象时,只关注对象提供的功能,不关注其内部细节。

    面向对象的特点:封装,继承,多态。

    JS中面向对象的组成:1.方法(函数):过程,动态的 2.属性(有所属关系的变量):状态,静态的

    对象是无序属性的集合,其属性可以包括基本值、函数、对象。每个属性都会有一个名字,每个名字映射到一个值上
    下面是创建一个对象的一些方法

    1.工厂模式

     1 function createPerson (name,sex) {//工厂方式构造一个对象
     2 
     3         //1.原料 
     4         var obj=new Object(); //new一个空白对象
     5         
     6         //2.加工
     7         obj.name=name;
     8         obj.sex=sex;
     9 
    10         obj.showName=function(){
    11             console.log('我的名字叫:'+this.name)
    12         }
    13 
    14         obj.showSex=function(){
    15             console.log('我是:'+this.sex+'的')
    16         }
    17         
    18         //3.出厂
    19         return obj;//这一步千万不能那下
    20     }
    21 
    22     var p1=createPerson('木木','女');//每用一次createPerson 就会new一个对象,每个对象都有一套自己的方法 造成资源浪费
    23     var p2=createPerson('扬扬','男');
    24 
    25     p1.showName();
    26     p1.showSex();
    27     p2.showName();
    28     p2.showSex();

    使用工厂方式构造对象步骤:
    1,原料
    2.加工
    3.出厂
    工厂方式不常用,因为有缺点:1.没有new 2.每个对象都有一套自己的函数,造成资源的浪费
    怎么解决这个两个问题呢?那么请看下面

    2.构造函数模式

     1 function Person (name,sex) {//构造函数   构造一个对象
     2         this.name=name;//this:当前的方法属于谁(在函数前面有new时会失效)
     3         this.sex=sex;
     4 
     5         this.showName=function(){
     6             console.log('我的名字叫:'+this.name);
     7         }
     8 
     9         this.showSex=function(){
    10             console.log('我是:'+this.sex+'的');
    11         }
    12        
    13     }
    14 
    15     var p1=new Person('木木','女');  //外面加new后Person函数里面就不用new一个空白对象
    16     var p2=new Person('扬扬','男');
    17 
    18     console.log(p1.showName==p2.showName);//fase
    19 
    20     p1.showName();
    21     p1.showSex();
    22     p2.showName();
    23     p2.showSex();

    注意:一般将Person称为构造函数,并且构造函数的名字首字母大写,这是编码规范。
    this:表示当前的方法属于谁,但是在这里当this碰到New时就会失效。
    用造函数模式解决了上面工厂模式没有New的问题
    这时就要想一想了在使用new操作符调用构造函数创建一个新实例的过程中发生了什么呢?一个新实例是怎么生成的呢?
    这种方式调用构造函数经历以下四个步骤:
    1.创建一个新对象
    2.将构造函数的作用域赋给新对象(因此this就指向了这个新对象)
    3.执行构造函数中的代码(为这个新对象添加属性)
    4.返回新对象

    1 function show(){
    2         alert(this);
    3     }
    4     show();//弹出window对象(当在全局作用域中调用一个函数时,this对象总指向window对象,全局函数属于window的一个方法)
    5     new show();//弹出obj (this会指向)新创建的一个对象

    面这个例子会看得更加清楚
    作为普通函数调用:

     1 var name = "mumu";
     2         function Person(name){
     3             this.name = name;
     4             this.show = function(){
     5             console.log("我是" + this.name);
     6             }
     7         }
     8 
     9         Person("javascript");
    10         console.log(name);//结果是javascript

    全局变量name被修改了

    作为构造函数调用:

     1 var name = "mumu";
     2         function Person(name){
     3             this.name = name;
     4             this.show = function(){
     5             console.log("我是" + this.name);
     6             }
     7         }
     8 
     9         var Name = new Person("HTML");
    10         console.log(Name.name);
    11         console.log(name);

    this指向新对象Name,全局变量name也没有变化

    那么问题又来了:

    1 console.log(p1.showName==p2.showName);//fase

    不同实例的showName()函数是不相同的,那么怎么解决这个问题呢?下面是一个解决办法

     1 function Person (name,sex) {//构造函数  
     2         this.name=name;//this:当前的方法属于谁(在函数前面有new时会失效)
     3         this.sex=sex;
     4 
     5         this.showName=showName;
     6         
     7     }
     8     function showName(){
     9             console.log('我的名字叫:'+this.name+'我是:'+this.sex+'的');
    10         }
    11 
    12     var p1=new Person('木木','女');  //外面加new后Person函数里面就不用new一个空白对象
    13     var p2=new Person('扬扬','男');
    14 
    15     console.log(p1.showName==p2.showName);//ture
    16 
    17     p1.showName();
    18     p2.showName();

    将showName定义成一个全局方法,这样每个实例共享的都是全局方法showName()。不相等的问题是解决了,可是如果构造函数里有大量的方法,这就造成代码中有大量的全局变量,这样我们自定义的引用类型就没有封装性了,资源还是照样浪费。那么怎么解决这个问题呢?请看原型模式

    3.原型模式

     1 function Person(name,sex) {//原型模式构造函数   
     2         Person.prototype.name=name;
     3         Person.prototype.sex=sex;
     4         Person.prototype.showName=function(){
     5             console.log('我的名字叫:'+this.name+'我是:'+this.sex+'的');
     6         }
     7     }
     8 
     9     var p1=new Person('木木','女'); 
    10     var p2=new Person('扬扬','男');
    11 
    12     console.log(p1.showName==p2.showName);//ture
    13     
    14     p1.showName();
    15     p2.showName();

    prototype(原型)返回对象类型原型的引用。这个属性是一个指针,指向对象。可以让所有对象实例共享它所包含的属性和方法,可以扩展系统对象,节省系统资源,所以这里解决了上面资源浪费问题。
    原型的问题:是当一个实例改变属性值时,所有实例对应的属性值也都跟着改变,无法初始化属性值,当为对象实例添加一个属性时,这个属性就会屏蔽原型对象中保存的同名属性,下面是个小例子:

     1 function Person(name,sex) {//原型模式构造函数   
     2         Person.prototype.name=name;
     3         Person.prototype.sex=sex;
     4         Person.prototype.showName=function(){
     5             console.log('我的名字叫:'+this.name+'我是:'+this.sex+'的');
     6         }
     7     }
     8 
     9     var p1=new Person('木木','女'); 
    10     var p2=new Person('扬扬','男');
    11     
    12     p1.name="兮兮";
    13 
    14     p1.showName();//兮兮 来自实例
    15     p2.showName();//扬扬 来自原型

    前面几种方法都各有各优缺点,那么把它们综合一下又会怎么样呢?

    4.组合使用构造函数模式和原型模式

     1 //构造函数模式定义实例属性
     2     function Person (name,sex) {   
     3         this.name=name;
     4         this.sex=sex;
     5     }
     6     
     7     //原型模式共用方法和共享属性
     8     Person.prototype.showName=function(){
     9             console.log('我的名字叫:'+this.name+'我是'+this.sex+'的')
    10         }
    11 
    12     var p1=new Person('木木','女'); 
    13 
    14     p1.showName();

    这种方法是最常用的,结合了两种方法的优点,最大限度地节省了内存

    5.动态原型模式

     1 function Person(name, age) {
     2     this.name = name;
     3     this.age = age;
     4 
     5         //方法
     6         if(typeof this.showName != 'function') {
     7             Person.prototype.showname = function() {
     8                 console.log("我的名字是: " + this.name);
     9             }
    10         }
    11     }
    12     var person1 = new Person("mumu", 17);
    13     person1.showname();

    动态原型方法可以通过检查方法是否有效,决定初始化的原型。这种方法堪称为完美,但是不能使用面向字面量重写原型,这样会切断现有实例与新原型之间的联系。

    6.寄生构造函数模式

     1 function createPerson(name, age) {
     2         var obj=new Object();
     3         obj.name = name;
     4         obj.age = age;
     5         obj.showName = function() {
     6             console.log("我的名字是:" + this.name);
     7         }
     8         return obj;
     9     }
    10     var person = new createPerson("mumu", 17);
    11     person.showName();

    此方法可以和工厂模式对比一下,创建实例方法与构造函数相同,其余与工厂模式相同。如果前面方法都不适用可以考虑一下这种方法,但是这种方法构造函数返回的对象与实例没有关系,也不能依赖instanceof判断对象类型,因此,如果可以使用其他模式这种方法建议还是不要使用。

    7.稳妥构造函数模式

     1 function Person(name, age) {
     2         var obj = new Object();
     3         //定义一些私有变量和函数
     4         obj.showName = function() {
     5             console.log("我的名字是:" + name); //定义的私有变量等只能通过showName访问
     6         }
     7         return obj;
     8     }
     9     var person1 = Person("兮兮", 17);
    10     person1.showName();

    所谓稳妥对象,指的是没有公共属性。这种方法适合用于在安全的环境下,因为它不使用new调用构造函数,也不使用this引用实例方法。若想访问其属性,只能通过showname方法来访问其内部私有属性。

  • 相关阅读:
    POJ 3468 A Simple Problem with Integers
    BZOJ 4430 Guessing Camels
    POJ 2309 BST
    POJ 1990 MooFest
    cf 822B Crossword solving
    cf B. Black Square
    cf 828 A. Restaurant Tables
    Codefroces 822C Hacker, pack your bags!
    [HDU 2255] 奔小康赚大钱
    [BZOJ 1735] Muddy Fields
  • 原文地址:https://www.cnblogs.com/amumustyle/p/5422214.html
Copyright © 2011-2022 走看看