介绍JavaScript面向对象

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zhaoxl0210/article/details/84065003

JavaScript中的引用类型

引用类型通常叫做类(class),也就是遇到引用值或者处理的对象。但是从严格意义上讲JavaScript并不是面向对象的,而是基于对象(object)的。之所以说是基于面向对象的原因是JavaScript中并没有类似Java中的多态,抽象,重载等面向对象语言中的概念。但是JavaScript中定义了"对象定义",在逻辑上等价于其他面向对象语言中的"类"的概念。 例如我们可以使用下面的代码创建Object对象的一个实例:

var obj = new Object() ;

JavaScript中的对象

在JavaScript中的Object对象类似于Java中的java.lang.Object对象,所有的对象都是由这个对象继承而来,也即是说Object中的所有属性和方法都会出现在其他对象中。

1 Object 对象的属性和方法

  • constructor : 对创建对象的函数的引用
  • Prototype : 对该对象的对象原型的引用。对于所有的对象,它默认返回 Object 对象的一个实例。
  • ToString() : 返回对象的原始字符串表示
  • ValueOf() : 返回最适合该对象的原始值。对于许多对象,该方法返回的值都与 {{{ToString?() 的返回值相同
  • javascript中定义属性和方法 在javascript中定义属性和其他语言类似:如下面的例子:
   function person(name){
     this.setName= function(newName){name = newName};
     this.getName= function(){
        return name;
     }
   }
   var p = new person("Lily");
   p.setName("Lucy");
   p.getName();

注: 除了上面的定义方式之外,在js中有一种比较重要的定义对象属性方法的常见的写法就是使用JSON对象。定义一个JSON对象,同时定义它的一些属性和方法。

2 JavaScript中一切都是对象

当我们了解了Object类的时候就可以理解为什么JavaScript中一切都是对象了。我们来看下面的代码

<script type="text/javascript">
    function car(){}
    var c = new car() ;
    /*证明c就是Object*/
    alert(c instanceof car) ;
    alert(car instanceof Function) ;
    alert(Function instanceof Object) ;
    /*证明一切都是Object*/
    alert(c instanceof Object) ;
    alert(car instanceof Object) ;
    alert(Function instanceof Object) ;
</script>

上面alert中的内容都是true,那么也就是我们声明出来的c就是一个Object,并且所有的一切都是Object。但是这里就又存在了一个疑问:JavaScript不是基于对象的么?从上面的例子可以发现类似java中的继承的概念:c是Object的子类。那这又是怎么回事呢?

3 JavaScript中内置对象(了解即可,这里就不举例说明了)

  • Global对象:也即window对象,它没有construct属性,所以不能用new进行构造,没有call属性,所以也无法像函数一样进行调用
  • Object对象:它是所有对象的基础,任何其它对象都是从object对象原型扩展而来。如果Object对象使用原型扩展了其它属性,那么所有对象将都具有此扩展属性
  • Function对象:使用function可以定义一个函数,在系统内部进行调用
  • Error对象:可以在发生错误的时候作为参数传递给catch子句,也可以使用new关键字构造自定义的error对象

继承机制的实现

现在我们来说明上面提出的疑问:JavaScript是基于面向对象,但是怎么存在继承呢?首先我们知道子类将继承所有父类的公共的属性和方法,包括构造和方法的实现。同时子类还可以添加父类中不存在的新的属性和方法,也可以覆盖父类中的属性和方法。

在Java中我们可以使用extends轻松的实现继承,JavaScript并没有提供。但是我们可以模拟继承,而且在JavaScript中的继承并非只有一种形式。

1 call()方法

基本用法

 <script type="text/javascript">
      function sayColor(sPrefix,sSuffix) {
          alert(sPrefix + this.color + sSuffix);  // 输出The color is blue,a very nice color.
      };

      var obj = new Object();
      obj.color = "blue";

      sayColor.call(obj, "The color is ", ",a very nice color.");
  </script>

说明:

  • 1. call()方法中的第一个参数用作this对象,其他的参数都是直接传递给函数自身。(this并不一定是执行该函数时的真正的this值,如果this的值是null或者是undefined,那么this就会自动指向全局变量,如果是浏览器,那么当然是window了。此时this会指向原始值的自动包装对象)
  • 2. sayColor在对象之外定义,显然它不属于任何对象,当时也可以使用关键字this。因为一个function也是一个对象。(javascript中函数即为对象)
  • 3. call()方法中的第一个参数是obj,也就是在sayColor中的this是obj。所以sayColor中的this.color就是blue。
  • 4. 另外的两个参数就是sayColor中的sPrefix和sSuffix。

使用继承

0.  <script type="text/javascript">
1.      function ClassA(sColor) {
2.          this.color = sColor;
3.          console.log(this) ;     
4.          this.sayColor = function () {
5.              alert(this.color);
6.          };
7.      }

8.      function ClassB(sColor, sName) {
9.           ClassA.call(this, sColor);

10.          this.name = sName;
11.          this.sayName = function () {
              alert(this.name);
12.          };
13.     }
      
14.      var objA = new ClassA("blue");
15.      var objB = new ClassB("red", "John");
16.      objA.sayColor();	//输出 "blue"
17.      objB.sayColor();	//输出 "red"
18.      objB.sayName();		//输出 "John"
19.  </script>

说明:

  • 1. objB本身并没有sayColor函数,这是因为通过call方式继承而来。在其中第9行的this是ClassB,第3行的this也是ClassB,所以第2行的this.colo就是ClassB中的 color,即red。这一特点和继承相符合:子类继承父类的方法,并拥有父类的所有属性。
  • 2.ClassB同时可以拥有新的属性和方法。在第10,11行。
  • 3.call相当于连接另一个对象的构造方法,类似于java中的super关键字的含义,在这里,相当于是在ClassB作用域下调用ClassA函数,很好的体现了继承。(call还能实现多继承)

2 prototype

在JavaScript中的继承是基于原型链的。看下面的例子

   <script type="text/javascript">
   1   function ClassA() {
   2   }
   3
   4   ClassA.prototype.color = "blue";
   5   ClassA.prototype.sayColor = function () {
   6       alert(this.color);
   7   };
   8
   9   function ClassB() {
   10  }
   11
   12   ClassB.prototype = new ClassA();
   13   ClassB.prototype.name = "";
   14   ClassB.prototype.sayName = function () {
   15       alert(this.name);
   16   };
   17   var objA = new ClassA();
   18   var objB = new ClassB();
   19   objA.color = "blue";
   20   objB.color = "red";
   21   objB.name = "John";
   22   objA.sayColor();
   23   objB.sayColor();
   24   objB.sayName();
   </script>

说明:

  • 1.和上面的例子不同的是,第一行ClassA的构造函数中没有参数,这个是使用原型链的标准。此外在函数体中没有定义属性和方法,都是在CalssA的构造函数之外通过ClassA.prototye.Xxx的方式定义的。
  • 2. 第12行就是继承的关键,我们需要使用ClassA中的全部属性和方法。当然我们可以通过ClassB.prototye.Xxx的方式逐个定义,使其相等。但是我们可以使用ClassB.prototype = new Xxx()的方式,将ClassA的实例赋予给ClassB,这样就更好了。第20和23也证明了ClassB继承了ClassA的属性和方法。
  • 3.我们从第一行中可以发现ClassA是一个Function,但是同时Function也是一个Object,而之前讲过,Object对象的属性:Prototype默认返回Object对象的一个实例。也就是说prototype实际上是Object的属性。
  • 4.从4,5行可以看出我们既可以使用prototype定义属性也可以定义方法,而且完全取决于你自己。因为prototype返回一个Object实例,自然就可以添加任意你喜欢的属性和方法了。
  • 5.类的实例可以通过"."的方式访问prototype定义过的属性方法,第19 - 24行

javaScript对象体系结构

javascript对象体系结构图

JavaScript中的this

  • this是javascript中理解类和继承的重要基础。this属性代表当前对象。如果用在全局变量中,那么它代表当前页面对象window,我们可以通过使用call和apply方法来改变this指针,(注意:this指针是在函数调用时改变的,并不是函数定义时)如下面的例子:
    function hello(){
        alert(this.say);
    }
    var say = "你好";
    hello();
    var test = {
        say:"欢迎访问",
        hello:hello
    }
    test.hello();
  • 1.开始时执行hello方法是全局的,相当于window.hello(),输出的是"你好",在下面调用的时候this指向了当前对象test,所以输出的是"欢迎访问"。
  • 2.在函数定义时,this指向的是window对象,在第一次执行的时候this指针不变,但是在第二次执行的时候this指针变成了test对象。this指针发生了变化。
  • this指针可以是全局对象、当前对象或者任意对象,这个要取决于函数的调用方式:在javascript中,函数有几种不同的调用方式:作为对象方法调用、作为函数调用、作为构造函数调用、使用apply和call进行调用。以下分别是这几种调用方式下的this指针:
    • 1.作为函数对象调用

由于函数也是对象,因此函数也可以作为对象的一个属性,此时函数就是该对象的方法,当使用该对象调用这个方法时,this当然指的是该对象 例子:

       var hello = {
        say:"welcome",
        test:function(name){
           this.say = name + " say:" + this.say;
        }
       };
     hello.test("jack");

此时的this就被绑定到hello对象中

  • 2.作为函数调用

在函数体内也可以直接调用,此时的this指的是全局对象window。例子:

     var say = "welcome";
     function hello(say){
       this.say = say;
     }

此时的this指的是全局对象。

  • 3.作为构造函数调用
         Hello.js
         function Hello(say){
           this.say = say
         }
    

this被绑定到新创建的对象上面。

  • 4.使用call或者apply调用(同上面的call方法中的举例)

JavaScript匿名函数

1 定义一个函数方式

首先需要说明的是在JavaScript中定义一个函数一般存在如下三种方式:

  • 1. 使用关键字function
       funtion sayHello(){alert("hello"); }
    

这种方式定义的函数,函数声明在整个程序执行之前的预处理就完成了。只要同处于一个作用域就可以访问到。

  • 2. 使用Function类
       var myFunction = new Function("x","alert(x)") ;
    

Function类中前面的参数就是在最后一个参数中需要传递的参数,也就是最后一个参数是函数的主体。使用Function类定义的函数中的参数必须都是字符串。

  • 3. 使用匿名对象
     var myFunction = function(x){alert(x) ;}
    

这种方式定义的函数,只能按照程序流程执行到定义的那一行才可以被声明,所以只能在定义之后才可以调用。

2 变量的作用域

变量的作用域无非就是两种:全局变量和局部变量。 在JavaScript中支持在函数的内部直接访问全局变量,同时在函数的外部自然就无法访问到函数内的局部变量了。 另外需要说明的是在函数的内部声明变量时候,一定要使用var关键字,否则的话,实际上你声明了一个全局的变量!!

3 示例

<html>
    <head>
        <title>匿名对象</title>
    </head>
    <body>
        <script type="text/javascript">
            // 测试函数作用域
            var NUM = 999 ;       // 全局变量
            function testNum(){
                alert(NUM) ;        
                var count = 100     //  局部变量
                TEST_NUM = 1 ;      //  全局变量
            }
            testNum() ;         //  999
            alert(count) ;      // error
            alert(TEST_NUM) ;   // 1  
            
            // 测试匿名函数
            var testFunction;
            testFunction();          //error
            testFunction=function(){     
                sayHello();          //sayHello works
                alert("testFunction works");
                
                return false;       // 虽然已经return,说明程序流程并没有执行,但是sayHello已经在预处理中处理了
                
                function sayHello(){
                    alert("hello");
                }
            }
            testFunction();        // 先输出hello , 再输出testFunction works , 这是因为sayHello程序的执行流程之前被调用。
        </script>
    </body>
</html>

4 匿名函数和this结合

<html>
    <head>
        <title>匿名对象</title>
    </head>
    <body>
        <script type="text/javascript">
            // 不使用this关键字
            objA={
                Calculate : function(num){
                    return num > 2 ? objA.Calculate(num-1) : num ;   // 将objA替换成this即可
                }
            }
            objB={
                Calculate : objA.Calculate 
            }
            alert(objB.Calculate(5)) ;  // 2
            objA = {} ;                 // 将objA清空
            alert(objB.Calculate(5)) ;  // error
        </script>
    </body>
</html>

说明:在上面的代码中objA中定义了一个递归,直到num的值为2。然后将objA = {}进行了清空,那么下面的输出就会出现错误了。

这个时候我们的this就可以派上用场了。将递归函数中的objA替换成this,这样的话将objA = {} 清空,但是并不会将objB进行清空。

JavaScript闭包

闭包在js中是一个难点,本人也只是懂得其中的一点基础,希望以下的介绍能够对初学者起到入门的作用

1变量的作用域

要理解闭包的概念,首先应该理解一下变量的作用域,它分为两种:全局变量和局部变量,在js中,函数内部可以直接访问函数外部的变量,例如:

     var say = "hello";
     function test(){
        alert(say);
     }
     test();

当然外部不能访问内部的变量,如下的访问时错误的:

     
     function test(){
        var say = "hello";
       // 
     }
     alert(say);

注意:在函数内部定义变量的时候需要加var,否则默认的声明的是全局变量

2.从外部获取局部变量

上面说了,在一般情况下是不能访问的,但是如果改变一下思路,这个问题就会迎刃而解了,就是在函数内部定义函数:

    function test1(){
       var say = "hello";
       function test2(){
         alert(say);
       }
       return test2;
    }
     var test = test1();
     test();

以上就是在函数test1的内部定义了函数test2,在test2中访问局部变量。这样就在函数外部访问到了局部变量。

3.闭包的概念

闭包,通俗的讲,其实就是能够访问其他函数内部变量的函数

4.闭包的用途

闭包主要有两大用途:一个是前面提到的可以访问函数内部的变量,二是让这些变量的值始终保存在内存中。

    function test1(){
    var say = 1;
    add = function(){
          say += 1;
        }
    function test2(){
      alert(say);
    }
    return test2;
  }
  var result=test1();
  result(); 
  add();
  result(); 

以上函数中,result实际上就是一个闭包函数,它一共执行了两次,这说明test1的变量say一直在内存中。并没有在调用test1以后自动清除。这里面有一个add方法,因为在定义它的时候前面没有var关键字,所以它是一个全局变量,并且它又是一个匿名函数,它实际上也是一个闭包,所以能够改变局部变量的值。

5.闭包的运行机制,你理解了吗?看下面两个例子:

      var name = "Lily";
      var test = {
          name = "Lucy";
          getName:function(){
               return function(){
                         return this.name;
                      }
          }
      };
      console.log(test.getName()());

输出 "Lily";

      var name = "Lily";
      var test = {
          name = "Lucy";
          getName:function(){
               var Dthis = this;
               return function(){
                         return Dthis.name;
                      }
          }
      };
      console.log(test.getName()());

输出 "Lucy". 
还有几个闭包的例子,看这里​http://www.cnblogs.com/zhangle/archive/2010/07/02/1770206.html

JavaScript脚本化Java

1什么是脚本化

脚本化可以使宿主程序具有脚本所描述的能力,比如JavaScript技术,JavaScript可以让原本是静态的HTML代码的页面变活、具有局部刷新等更高级的功能。应用程序一般是以二进制的形式发布的,用户很难根据自己的需求对其进行定制。脚本化是通过用户自己设计脚本,然后将其注入到应用中,使得应用的行为得到改变。

2看这里简单的例子

​http://han2000lei.iteye.com/blog/353253 

 

 

猜你喜欢

转载自blog.csdn.net/zhaoxl0210/article/details/84065003