自己以前从来没有接触过javascript的,最近HTML5炒得很火,好像Flash马上就没有前途了一样。小组最近时间空下来就搞了个技术沙龙,每个人研究下HTML的一些知识,为以后的职业发展做些准备。
下面整理了下关于javascript的面向对象的一些知识。
1.关于javascript的类
function Person(myName,mySex){ this.name = myName; this.sex = mySex; this.showInfo = function (){ return ("my name is " + this.name + " ," + this.sex); } }
this 代表的类似于全局变量
var 代表的类似于私有变量
2.对于类的使用 可以看到跟标准的OO很像的。
function testClass(){ var p = new Person("beauty", "female"); p.sex = "male"; document.write(p.showInfo()); } function showConstructor(){ var p = new Person("beauty", "female"); document.write(p.constructor); } function referenceParameter(){ var p = new Person("beauty", "female"); var name = p.name; var sex = p["sex"]; } function referenceMethod(){ var p = new Person("beauty", "female"); var info = p.showInfo(); var info2 = p["showInfo"](); }
3.prototype 关键字
prototype自动的在构造函数中生成,可以动态的为类定义公共的变量和公共的方法.
prototype还有一个默认的属性:constructor,是用来表示创建对象的函数的(即我们OOP里说的构造函数)。constructor属性是所有具有prototype属性的对象的成员。它们包括除Global和Math对象以外的所有JScript内部对象。constructor属性保存了对构造特定对象实例的函数的引用。
对于对象的prototype属性的说明,JScript手册上如是说:所有 JScript 内部对象都有只读的 prototype 属性。可以向其原型中动态添加功能(属性和方法),但该对象不能被赋予不同的原型。然而,用户定义的对象可以被赋给新的原型。
对于JScript的解释引擎,它在处理"."或"[keyName]"引用的对象的属性和方法时,先在对象本身的实例(this)中查找,如果找到就返回或执行。如果没有查找到,就查找对象的prototype(this.constructor.prototype)里是否定义了被查找的对象和方法,如果找到就返回或执行,如果没有查找到,就返回undefined(对于属性)或runtime error(对于方法)。
function sayHello(){ return ("Hello"); } function prototypeFunc(){ var p = new Person("beauty", "female"); Person.prototype.sayHello = sayHello; Person.prototype.sayHi = function(){ return ("Hi"); } var p2 = new Person("ugly", "female"); document.write(p2.sayHello() + "," + p2.sayHi() + "," + p2.showInfo()); }
注意:
prototype != static
define by Class(Person),used by instance(p)
4.__proto__ 属性
var p = new Person("a","b");
我们来看看这个new究竟做了什么?我们可以把new的过程拆分成以下三步:
<1> var p={}; 也就是说,初始化一个对象p。
<2> p.__proto__=Person.prototype;
<3> Person.call(p);也就是说构造p,也可以称之为初始化p.
关键在于第二步,我们来证明一下:
var Person = function () { };
var p = new Person();
alert(p.__proto__ === Person.prototype);
这段代码会返回true。说明我们步骤2的正确。
我们在这里简单地说下。每个对象都会在其内部初始化一个属性,就是__proto__,当我们访问一个对象的属性时,如果这个对象内部不存在这个属性,那么他就会去__proto__里找这个属性,这个__proto__又会有自己的__proto__,于是就这样一直找下去,也就是我们平时所说的原型链的概念。
按照标准,__proto__是不对外公开的,也就是说是个私有属性,但是Firefox的引擎将他暴露了出来成为了一个共有的属性,我们可以对外访问和设置。
function __protoFunc(){ var p = new Person("beauty", "female"); p.__proto__.story = function(){ return ("long long ago...there was a..."); } p.__proto__.mom = "Joy"; var p2 = new Person("handsome", "male"); document.write(p2.showInfo() + "--" + p2.mom + "" + p2.story()); }
所以p.__proto__.mom实际是修改了Person的prototype了。
5.Return,Object,get,set
return跟其他程序的return关键字功能一样:
function ReturnFunc(){ return{ name:"Joy", sex:"female", showInfo:function(){ return ("Hi, I am " + this.name, + " " + this.sex); } } } function testRetunFunc(){ var test = new ReturnFunc(); document.write(person.shoInfo()); }
任何一个类都是基础自Object的
function PrototypeObject(){ }
function prototypeObjTest(){ PrototypeObject.prototype = { name:"Joy", sex:"femal", showInfo:function(){ return ("Hi I am " + this.name + "---" +this.sex); } } var test = new PrototypeObject(); document.write(test.name + "-----" + test.showInfo()); }
get set 方法和普通方法一样,只不过你可以设定一些特别的名字就可以了。譬如getLabel, setLabel等方法。
6.继承
1 就是给用户自定义对象赋新原型
function ChildClass(){ } function extendTest1(){ ChildClass.prototype = new Person("beauty child","baby girl"); var child = new ChildClass(); document.write(child.showInfo()); }
但是这样的继承有些问题,例如:
function Person(name,age)
{
var gender = 1;
this.showInfo = function()
{
document.write(gender++ + "person" + this.age);
}
this.name = name;
this.age = age;
}
function Employee2()
{
}
function clickHandler()
{
Employee2.prototype = new Person("kenny",19);
var test = new Employee2();
test.showInfo();
var test2 = new Employee2();
test2.showInfo();
}
你会发现gender第一是1,第二次是2,就是说私有变量没有回复原始值。
如果在test2之前再Employee2.prototype = new Person("kenny",19);赋一次原型,就不会出现此问题。
这个问题还没有找到找到解释。
2.在子类中使用$super来实现。
function ChildClass1(myName,mySex){ this.$super = Person; this.$super(myName, mySex); }
这种方法是最好的,没有上面说的那些问题,建议以这样的方式来做继承。
7.Static静态的方法和变量
Person.staticProperty = "123"; Person.showInfo = function(){};
和真正的oo一样,static不能被继承。
静态类:
function StaticClassTest(){ throw new Error("This is static class,can not be instance!"); }
8.override & overwrite
和真正的oo一样,也支持重载和重写。
还可以参考一些原型链的文章,有助于理解:
http://hi.baidu.com/mjy_camilla/item/77e9bbef2a6f58d9eb34c958
http://blog.youkuaiyun.com/junkaih2008/article/details/2653142