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

    一 面向对象的名词解释:

    对象是一个容器,封装了属性(property)和方法(method)

    属性:事物的特性;

    方法:事物的功能;

    对象:事物的一个实例;

    原型:JS函数中中由prototype属性引用的一个对象,即原型对象(原型 );

    二 对象定义的两种方式

    1 字面量的方式进行定义

    1         var  obj = {
    2                     name: "Tom ",
    3                     sex: " man",
    4                     age:19,
    5                     run:function(){
    6                         console.log("一天跑一公里");
    7                     }
    8           }

    2 使用 new Object() 进行定义

    1         var   obj = new  Object();
    2          obj.name = "Tom ";
    3          obj.sex = " man";
    4          obj.age = 19;
    5          obj.run = function(){
    6                      console.log("一天跑一公里");
    7          }

    三. 类和对象

    1 什么是类(Class)?

    具有相同特性(数据元素)和行为(功能)的对象的抽象就是类。因此,对象的抽象是类,类的具体化就是对象,也可以说类的实例是对象,类实际上就是一种数据类型。类具有属性,它是对象状态的抽象,用数据结构来描述类的属性。类具有操作,它是对象行为的抽象,用操作名和实现该操作的方法来描述。

    2类和对象的区别:

    类(Class)是一个抽象的概念,对象则是类的具体实例。

    比如:人是一个类,司马迁,李白,杜甫都是对象;首都是一个类,则北京,伦敦,华盛顿,莫斯科都是对象;动物猫是一个类,则Kitty、Grafield 和 Doraemon 都是对象。
    我们可以说 Kitty 猫的体重是 1.5kg,而不能说猫类的体重是 1.5kg;可以说李白是诗人,而不能说人类是诗人。状态是描述具体对象而非描述类的,行为是由具体对象发出的而非类发出的。

    3 类和对象的关系

    类与对象的关系就如模具和铸件的关系,类实例化的结果就是对象,而对象的抽象就是类,类描述了一组有相同特性(属性)和相同行为的对象。 

    1     class person{ }//这个是类
    2     $obj = new person();//类的实例化就是对象

    四.创建对象的三种方式

    4.1  工厂模式,使用简单的函数创建对象,为对象添加属性和方法,然后返回对象

     1  // Class 模板
     2     function  Person(name,sex,age){
     3         var  obj = {};
     4         obj.name = name;
     5         obj.sex = sex;
     6         obj.age = age;
     7         obj.run = function(){
     8             console.log("每天坚持跑步");
     9         }
    10         return obj;
    11     }
    12     // 实例化
    13     var  person1 = Person("Tom","sex",19);
    14     //操作
    15     person1.run();  //  输出结果:每天坚持跑步
    • 工厂模式实际是一个包含参数的函数封装,调用后返回拥有参数和方法的对象,多次调用解决重复代码问题,但是存在对象识别的问题,同时也拥有构造函数模式相同的缺点

    4.2 构造函数模式。创建自定义引用类型,可以像创建内置对象实例一样使用new操作符,这种方法的缺点是,构造函数的每个成员都无法复用,每次创建出的对象都只有私有变量和私有方法,不能实现共用.

     1 //构造函数(这里就创建了一个Class模板)
     2     function Person(name,sex,age){
     3         this.name = name;
     4         this.sex = sex;
     5         this.age = age;
     6         this.run = function(){
     7             console.log("每天坚持跑步");
     8         }
     9     }
    10  // 实例化 ( new Object())
    11     var person1 = new Person("Tom","man",19);
    12  //操作
    13     person1.run();// 每天坚持跑步

    4.2.1 构造函数的改进

     1    // 构造全局的对象
     2     var  action = {
     3         run:function(){
     4             console.log("每天坚持跑步");
     5         }
     6     }
     7     //构造函数
     8     funcction(name,sex,age){
     9         this.name = name;
    10         this.sex = sex;
    11         this.age = age;
    12         this.run = action.run;
    13     }
    14     //实例化
    15     var person1 = new Person("Tom","man",19);
    16     person1.run();

    分析: 为什么要改进构造函数?
    我们都知道当实例化一个对象后,那么这个对象就拥有了模板的属性和方法,
    当我们使用方法时首先会在内存中开辟一份空间,然后在执行相应的操作。假设我们实例化一万个对象,那么这一万个对象在执行方法时都要在内存中开辟空间,这样只会浪费内存的空间,这时如果能用一个操作代替一万个操作那样岂不是美哉,所以小编这里用了一个全局的对象,即使是一万个对象使用这个方法只会在内存中开辟一份空间。
    但是这也有缺点,我们都知道全局变量和局部变量,全局变量易造成污染并且声明周期比较长,那么全局对象也是一样的,有没有一种方式可以不用全部对象呢?当然有,见下面的第三种创建模式

    4.3 原型模式,使用构造函数的prototype属性来指定共享的属性和方法,即使用构造函数定义实例属性,使用原型定义共享的属性和方法

     1 //构造函数
     2     function Person(name,sex,age){
     3         this.name = name;
     4         this.sex = sex;
     5         this.age = age;
     6     }
     7     //使用原型对象   Object.prototype
     8     Person.prototype.run = function() {
     9         console.log("每天坚持跑步");
    10     }
    11     //实例化
    12     var person1 = new  Person("Tom","man",19);
    13     person1.run();//  每天坚持跑步

    五.构造函数、原型对象、实例化对象三则的关系

    首先先明白几个属性:
    __proto__: 对象的原型。所有对象都有(包括函数)

    prototype:函数的原型对象。只有函数(准确来说是构造函数)才有

    constructor:对象上的一个属性,默认指向这个原型的构造函数.

    六.彻底理解js中this的指向

    首先必须要说的是,this的指向在函数定义的时候是确定不了的,只有函数执行的时候才能确定this到底指向谁,实际上this的最终指向的是那个调用它的对象(这句话有些问题,后面会解释为什么会有问题,虽然网上大部分的文章都是这样说的,虽然在很多情况下那样去理解不会出什么问题,但是实际上那样理解是不准确的,所以在你理解this的时候会有种琢磨不透的感觉),那么接下来我会深入的探讨这个问题。

    eg1:

    1       function  show(){
    2             var user = "Tom";
    3             console.log(this.user);//undefined
    4             console.log(this);//window
    5         }
    6         show();
    按照我们上面说的this最终指向的是调用它的对象,这里的函数show()实际是被Window对象所调用出来的,下面的代码就可以证明。
    1      function  show(){
    2             var user = "Tom";
    3             console.log(this.user);//undefined
    4             console.log(this);//window
    5         }
    6         window.show();
    和上面代码结果一样,所以此时this是window调用出来的
    

      eg2:

    1            var show = {
    2             user:"Tom",
    3             fn:function(){
    4                 console.log(this.user);//Tom
    5             }
    6         }
    7         show.fn();
    这里的this指向的是对象show,因为你调用这个fn是通过show.fn()执行的,那自然指向就是对象show,这里再次强调一点,this的指向在函数创建的时候是决定不了的,在调用的时候才能决定,谁调用的就指向谁,一定要搞清楚这个。
    

      要想彻底搞懂this的指向请看下面的例子

    eg3:

    1           var show = {
    2             user:"Tom",
    3             fn:function(){
    4                 console.log(this.user);//Tom
    5             }
    6         }
    7         window.show.fn();
     这段代码和上面的那段代码几乎是一样的,但是这里的this为什么不是指向window,如果按照上面的理论,最终this指向的是调用它的对象,这里先说个而外话,window是js中的全局对象,我们创建的变量实际上是给window添加属性,所以这里可以用window点show对象。
    

      这里先不解释为什么上面的那段代码this为什么没有指向window,我们再来看一段代码

     1      var show = {
     2             a:20,
     3             b:{
     4                 a:22,
     5                 fn:function(){
     6                     console.log(this.a);// 22
     7                 }
     8             }
     9         }
    10         show.b.fn();

     这里同样也是对象show点出来的,但是同样this并没有执行它,那你肯定会说我一开始说的那些不就都是错误的吗?其实也不是,只是一开始说的不准确,接下来我将补充一句话,我相信你就可以彻底的理解this的指向的问题。

      情况1:如果一个函数中有this,但是它没有被上一级的对象所调用,那么this指向的就是window,这里需要说明的是在js的严格版中this指向的不是window,但是我们这里不探讨严格版的问题,你想了解可以自行上网查找。

      情况2:如果一个函数中有this,这个函数有被上一级的对象所调用,那么this指向的就是上一级的对象。

      情况3:如果一个函数中有this,这个函数中包含多个对象,尽管这个函数是被最外层的对象所调用,this指向的也只是它上一级的对象,例子3可以证明,如果不相信,那么接下来我们继续看几个例子。

    1        var show = {
    2            a:20,
    3            b:{
    4                fn:function(){
    5                    console.log(this.a);// undefined
    6                }
    7            }
    8        }
    9        show.b.fn();

    尽管对象b中没有属性a,这个this指向的也是对象b,因为this只会指向它的上一级对象,不管这个对象中有没有this要的东西。

    还有一种比较特殊的情况,eg4:

     1     var show = {
     2            a:20,
     3            b:{
     4                a:22,
     5                fn:function(){
     6                    console.log(this.a);// undefined
     7                    console.log(this);//window
     8                }
     9            }
    10        }
    11        var d = show.b.fn;
    12        d();

    这里this指向的是window,是不是有些蒙了?其实是因为你没有理解一句话,这句话同样至关重要。

     this永远指向的是最后调用它的对象,也就是看它执行的时候是谁调用的,例子4中虽然函数fn是被对象b所引用,但是在将fn赋值给变量d的时候并没有执行所以最终指向的是window,这和例子3是不一样的,例子3是直接执行了fn。

    this讲来讲去其实就是那么一回事,只不过在不同的情况下指向的会有些不同,上面的总结每个地方都有些小错误,也不能说是错误,而是在不同环境下情况就会有不同,所以我也没有办法一次解释清楚,只能你慢慢地的去体会。

    构造函数版this:

    1           function Fn(){
    2                 this.user = "Tom";
    3             }
    4         var a = new Fn();
    5         console.log(a.user); //Tom

    这里之所以对象a可以点出函数Fn里面的user是因为new关键字可以改变this的指向,将这个this指向对象a,为什么我说a是对象,因为用了new关键字就是创建一个对象实例,理解这句话可以想想我们的例子3,我们这里用变量a创建了一个Fn的实例(相当于复制了一份Fn到对象a里面),此时仅仅只是创建,并没有执行,而调用这个函数Fn的是对象a,那么this指向的自然是对象a,那么为什么对象a中会有user,因为你已经复制了一份Fn函数到对象a中,用了new关键字就等同于复制了一份。

    当this碰到return:

    1      function Fn(){
    2             this.user = "Tom";
    3             return {};
    4         }
    5         var a = new Fn();
    6         console.log(a.user);//undefined

    继续:

    1      function Fn(){
    2             this.user = "Tom";
    3             return  funciton(){};
    4         }
    5         var a = new Fn();
    6         console.log(a.user);//undefined

    goon:

    1  function Fn(){
    2             this.user = "Tom";
    3             return  1;
    4         }
    5         var a = new Fn();
    6         console.log(a.user);// Tom

    再继续:

    1      function Fn(){
    2             this.user = "Tom";
    3             return undefined;
    4         }
    5         var a = new Fn();
    6         console.log(a.user);//Tom
    如果返回值是一个对象,那么this指向的就是那个返回的对象,如果返回值不是一个对象那么this还是指向函数的实例
    1        function Fn(){
    2             this.user = "Tom";
    3             return null;
    4         }
    5         var a = new Fn();
    6         console.log(a.user);//Tom

    虽然null也是对象,但是在这里this还是指向那个函数的实例,因为null比较特殊

     总结  this 指向问题  ,最后返回值如果是非引用类型堆返回值没有影响 如果是引用类型  ,引用类型的返回值会取代this所指向的对象.

  • 相关阅读:
    大话设计模式---单一职责原则
    大话设计模式---策略模式
    计算机网络(二)
    计算机网络(一)
    栈与队列

    数据库面试题——基本概念
    链表
    【Essential c++】——(三)泛型编程风格
    【转载】学习JAVA WEB的路线
  • 原文地址:https://www.cnblogs.com/lvlisn/p/11752507.html
Copyright © 2011-2022 走看看