在java里,咱们定义类的时候用的是class关键字,可是JavaScript中class是保留字,另有用途,因此咱们要采用其余的方法来定义JavaScript中的类。javascript
定义类java
利用JavaScript中的function关键字,类名首字母通常采用大写,如:浏览器
function Person(id,name,age){ this.id = id; this.name = name; this.age = age; }
回想java的类中会有一个与该类同名的构造函数,即便开发者本身没有写,java虚拟机也会给出一个默认的构造函数。而JavaScript这里,上面这个类自己其实也是一个构造函数。这里记住一句话: “构造函数为对象的‘类’提供一个名字,并初始化属性。”咱们能够用下面的方法来使用这个类:
var per = new Person("001","Xiao Wei","12");
上面那个构造函数里的this指针(严格意义上this不是指针,只是咱们把它想象为指针会容易理解一些)指向的变量便是Person类的数据成员(或者叫属性),访问权限是public。java的类中,除了有属性以外,还有方法(也就是c里的函数)。下面咱们为JavaScript类添加函数。闭包
function Person(id,name,age){ this.id = id; this.name = name; this.age = age; this.getInformation = function(){ return "编号:"+this.id+";姓名:"+this.name+";年龄:"+this.age; }; }
上面是一种最直接的办法来为类添加属性,然而这不是好的办法,缘由在于对客观事物的描述不正确,由于属性是每一个实例(也就是对象)都有一份,而方法应该不须要,由于方法是对数据进行处理,是公用的,因此,更好的解决办法采用prototype原型方式。
function Person(id,name,age){ this.id = id; this.name = name; this.age = age; } Person.prototype.getInformation = function(){ return "编号:"+this.id+";姓名:"+this.name+";年龄:"+this.age; };
这里之因此可以采用原型方式是由于 每一个JavaScript对象都包含着对它的原型对象的内部引用。其实不只方法,属性也能够采用prototype原型方式。这里再记住一句话: “方法和其余不变属性放在原型对象中。”
类已经经过function关键字实现了,这是一种实现方式,这种方式实现起来简单、通俗易懂,其实还有一种实现方式,实现起来很是优雅,咱们看下面代码:并发
var Class={ create:function(){ return function(){ this.inital.apply(this,arguments); }; } }; /*定义Person类*/ var Person=Class.create(); Person.prototype={ inital:function(id,name,age){ this.id = id; this.name = name; this.age = age; }, getInformation:function(){ return "编号:"+this.id+";姓名:"+this.name+";年龄:"+this.age; } };
关键代码在于:this.inital.apply(this,arguments);这样一行,Class自己是一个对象,有一个方法叫作create,此方法返回一个函数指针,其中函数体内执行this.inital.apply(this,arguments);this指向是的是当前对象,在这里就是Person,apply方法是更改initial方法的做用域,arguments是参数列表。关于apply更详细的解释能够参见我以前的学习笔记《JavaScript中call()与apply()有什么区别?》。app
this函数
关于this的详细用法我已在读书笔记《JavaScript中的this如何使用》中有介绍。这里再啰嗦几小句。oop
在JavaScript中,并无严格的面向对象概念,天然也没有类的构造函数这样的概念。var o=new Obj();这样的语法,看起来彷佛和Java/C++至关相似,可是它背后的执行过程是不一样的。首先,解释器会new一个空的Object对象。而后将这个空的Object,做为隐藏的参数传递给function Obj()。在Obj函数中访问到的this,其实就是这个传入的空的Object 对象。这就是所谓:“this关键字关联于执行时的做用域”的含义。学习
若是你想把一个函数做为“构造函数”,那么就不要在函数的最后加上return语句。由于若是没有return语句,new算符返回的就是那个被操做过之后的this。一旦你经过return返回了别的东西,这个this就被废弃掉了。this
匿名类
var class1 = {p1:value1,p2:value2};
这个也能够写成
var class1 = {}; class1.p1 = value1; class1.p2 = value2;
首先全部的匿名类都是继承于Object核心对象的,var class1={} 意味着实例化了一个Object对象,它拥有Object对象的原生属性和原生方法。可是不能为匿名类添加原生方法,例如这样写是错误的:
class1.prototype.func1 = function(){};
你也不能尝试用new() 方法来构造一个新的与class1有相同的属性的新对象,由于它已经实例化了。如下写法也是错的:
var classB = new classA();
这是没法构造的,
准确的说,匿名类其实是继承于Object的某一个实例,至关于C#中的静态类。你能够为它添加方法和属性。例如:
class1.func1 = function(){};
调用的时候就这样:
class1.func1(); //酷似C#中的静态类
可是你能够为Object添加原生函数,这样你的匿名类(其实是全部的类)都有这个方法。例如:
var class1 = {}; class1.p1 = value1; class1.p2 = value2; Object.prototype.func1 = function(){ alert("1") }; class1.func1();
是没有问题的,可是这样一来,全部的实例化对象都有了func1()方法。实际应用中应该避免给Object类添加原生方法。
匿名函数
先说说关于Javascript的函数:能够这样说,JavaScript中一切皆是对象,function天然不例外,function能够做为函数,类,也能够当成一个被函数对象返回。
看下面的例子:
function a(){ alert("Hello Febird!"); this.aa = "aa"; this.show = function(){ alert(this.aa); }; this.sayHello = function(){ return function(){alert("hello");}; }; } var aaa = new a(); aaa.show(); aaa.sayHello();
其中最外面的一个function是定义了一个类 a ,它有属性aa,方法show(),sayHello();这两个都是匿名函数,而sayHello中的function即是函数做为一个返回值的例子。
实际上能够这样想,匿名函数就是一块没有命名的代码块,当把它赋值给别的变量的时候,那么那个变量就是一个函数,准确的说那是一个函数指针。
在JavaSript中,匿名函数是颇有特色的东西了,也是很是有用,也是有些难以理解的。
好比在写Ajax引用的时候,若是不依靠别的JSF,本身写一个通用的Ajax话,通常这样写:
var xhr = new XMLHttpRequest(); //已经封装,能够适应不一样的浏览器; function DoAjax(){ xhr.onreadystatechange=processFunction; xhr.open("GET",url,true); xhr.send(null); } function processFunction(){ //do something with XMLHttpRequest; if(xhr.readState!=4||xhr.status!=200) return false; alert(xhr.responseText); }
在通常的Ajax引用中,也许只要一个XMLHttpRequest对象,并且onreadystatechange的处理函数必须没有参数,有参数就出错,因此,通常常常会写一个全局变量XMLHttpRequest,再在processFunction中用到这个全局变量,可是若是我要创建几个XMLHttpRequest的并发链接怎么办呢?这个就不能用全局变量了,可是处理函数又不能有参数,怎么搞,能够这样:
function DoAjax(){ var xhr = new XMLHttpRequest(); xhr.onreadystatechange = processFunction(xhr); xhr.open("GET",url,true); xhr.send(null); } function processFunction(_xhr){ return function(){ //do something with XMLHttpRequest; if(_xhr.readState!=4||_xhr.status!=200) return false; alert(_xhr.responseText); }; }
怎么理解?虽然processFunction函数有参数,可是它返回的函数没有参数!而这两个函数之间是怎么进行的值传递呢?
这里不妨引用一句话:
“为了函数可以正确的执行,须要被函数使用的,词法做用域中的,非全局数据,存在于函数的闭包之中。”
能够这样理解:
当咱们把processFunction()返回的函数,在processFunction以外使用的时候,依然要记得本身被定义时的上级做用域中的各类变量的值。这些须要被记住的值,就是“闭包”。
原生对象
原生,即prototype,它提供了扩展、改造原有对象的方法。例如咱们能够为已知对象,包括JavaScript的核心对象Array,Number,Math,Object,Boolean等和自定义类添加方法或者属性。
例如:
Number.prototype.toHexString = function () { return this.toString(16); }; var num = 10; alert(num.toHexString());
输出A;
你能够为Object对象添加方法,这样,之后任意一个对象都有这个方法,由于其它对象都是从Object继承而来的。
你也能够再造现有函数
Function.prototype.toString = function () { return “Function Locked”; };
参考资料: