1.构造函数

例:Animal = function(name,age){

     this.name = name;

     this.age = age;

    }

    var animal = new Animal("cat",5);

    alert(animal.name+" "+animal.age);

2.模拟静态属性

例:Animal = function(name,age){

     this.name = name;

     this.age = age;

     Animal.insCont++;

    }

    Animal.insCont = 0;

    var animal = new Animal("cat",5);

    alert(Animal.insCont+"  "+animal.insCont);// 1 undefined

  function的静态属性,和Java类静态属性最大的区别就是,前者的实例对象不能访问function类的静态属性。只能用类名(function的名字)直接调用。

3.定时器:setTimeoutsetInterval。前者只执行一次,后者每隔相同的时间就执行,除非取消。取消定时器的方法分别为:clearTimeoutclearInteral.

例:var myFn = function(){

     var date = new Date();

     document.body.innerHTML = date.toLocaleString();

   }

   window.setTimeout(myFn,1000); // 只更新一次

   window.setInterval(myFn,1000); // 每1秒钟更新

另外一种写法:直接把函数写在第一个参数的位置

  window.setInterval(function(){

 

     var date = new Date();

     document.body.innerHTML = d.toLocaleString();

 

  },1000);

 Ext.util.TaskRunnerExt.TaskMgr就用到了上述内容。

4.给回调函数传参(这里需要重点理解)。上例中myFn就是一个回调函数。“回调”的直观理解就是:不是让脚本引擎现在就执行,而是我们设置好放在这里,一旦需要的时候你在“回过头来”调用。

  window.setInterval(myFn,1000);不是立即执行myFn,而是每隔一秒钟的时间,再来调用它。

  现在的问题是,怎么给myFn传递参数

  window.setInterval(myFn("cat"),1000); // 这种做法是错误的,因为里面的("cat")是一个运算符,当JS执行到这一行的时候,直接就调用了myFn这个函数,而不是由定时器调用。

解决办法就是:把第一个参数myFn("cat")写在一个函数里面,封装起来

  var myFn = function(){

     var date = new Date();

     document.body.innerHTML = date.toLocaleString();

   }

   window.setTimeout(function(){

     myFn("cat")

   },1000); // 只更新一次

  这样就,每个1秒执行function(){ myFn("cat") }这个函数,这个函数就会调用myFn并且传参。我们把这个函数提取出来,就变成了下面的形式:

  var myFn = function(){

     var date = new Date();

     document.body.innerHTML = date.toLocaleString();

   }

   var callBack = function(name){

     return function(){

myFn(name);

     }

   }

   window.setTimeout(callBack("cat"),1000);

   这样,当脚本引擎执行到最后一行的时候,先执行callBack("cat"),返回function(){myFn("cat");},这样每隔1秒钟就执行myFn("cat")。

   接下来把callBack这个函数给抽象出来就变成:

   var myFn = function(){

     var date = new Date();

     document.body.innerHTML = date.toLocaleString();

   }

   var callBack = function(fn,args){

     return function(){

        fn.call(window,args);  // window绑定fn的this

     }

   }

   window.setTimeout(callBack(myFn,"cat"),1000);

5.函数原型prototype

例:var obj = {};

    alert(obj.prototype);  // undefined 注意不是抛出异常

    alert(obj.constructor);// function Object(){ [native code] }

说明:1 var obj = {};其实是调用了Object构造函数。

      2 普通的JS对象实例,没有prototype这个属性。

      3 obj.constructor是Object的构造函数。

      4 实例可以通过某个机制,能够访问其构造函数的prototype的属性和方法。但是,普通对象不能对其构造函数的prototype属性进行修改

6.向prototype添加自定义属性

例:Animal = function(name){

     this.name = name;

   }

   Animal.prototype.sayHello = function(){

     alert("hello,my name is:" + this.name);

   }

   var animal = new Animal("cat");

   animal.sayHello();

效果和下面相同:

 Animal = function(name){

     this.name = name;

     this.sayHello = function(){

        alert("hello,my name is:" + this.name);

     }

   }

   var animal = new Animal("cat");

   animal.sayHello();

但是,前者只是给类Animal生成一份sayHello方法,后者会给每一个实例对象都生成一份sayHello方法。prototype方式的优点可想而知。

7.原型查找机制。以上述为例,sayHello这个函数被“存储”在了Animal.prototype上,animal实例上并没有sayHello这个方法。这时候依据JS的“原型查找”机制:如果从实例对象上没有找到指定的属性,那么就尝试从它的构造函数的prototype上去找;如果找不到,继续找prototype构造函数的prototype。直到找到了为止,否则返回null终止。

例:Animal = function(name){

     this.name = name;

   }

   Animal.prototype.sayHello = function(){

     alert("my name is :" + this.name);

   }

   Cat = function(name){

     this.name = name;

   }

   Cat.prototype = new Animal("animal");

   var cat = new Cat("cat");

   cat.sayHello();  // my name is :cat

 流程如下:首先在cat对象上找sayHello方法,没有找到,尝试到Cat.prototype上去找。此时,Cat.prototype已经被赋值成了new Animal("animal")实例,还是没有找到,又到Animal.prototype上去找,找到即返回。

 但是,为什么结果显示"cat"而不是"animal"?因为在Cat的构造函数中有this.name = name;根据原型查找机制的规则会首先检测对象自身的属性,当没有检测到自身的属性的时候才回去原型上去找。

 这是不是闻到了一点儿Java中继承的味道?

8. 重写,相当于Java的override。根据之前的查找机制很容易理解

例:Animal = function(name){

     this.name = name;

    }

    Animal.prototype.sayHello = function(){

     alert("my name is:"+ this.name);

    }

    var cat = new Animal("cat");

    cat.sayHello = function(){

       alert("my name is :"+ cat.name); //cat

    }

    cat.sayHello(); // 调用实例对象自己的sayHello方法。

9.原型赋值机制

例:Animal = function(){}

   var a1 = new Animal();

   Animal.prototype.name = "cat";

   alert(a1.name);   // cat

   var a2 = new Animal();

   alert(a2.name);   // cat

虽然,在new出了a1这个对象之后才向Animal.prototype动态添加了name属性,a1.name还是被赋了值。说明:首先,实例对象的属性也是按照运行时的“查找”机制去查找的,否则a1.name为undefined。其次,向prototype添加、删除属性会“立即”影响到所有对象实例。查找机制:如果对象上找不到属性,则会到原型上去找。而对于赋值机制:只能在确定的地方赋值,而且给实例对象赋值是不会影响到prototype的。