javascript没有类的概念,经过函数实现构造函数,经过new运算符来建立对象javascript
function Person(name, age, job) { this.name = name; this.age = age; this.friends = ["A","B"]; this.sayname = function(){ alert(this.name); }; } var P = new Person("P",22,"coder");
Person与普通函数并没有区别,若是直接调用则是向this(window)对象添加属性java
用new操做符实现了4个步骤:c++
上述方法称为构造函数模式,每个对象互相独立,其属性和方法都独立建立,耗费空间,尤为是方法,没必要要独立建立。闭包
原型模式:每个函数都有一个原型属性,默认的原型属性有一个constructor域指向函数,原型为全部函数new出的对象所共有。相似于c++中的static属性或方法。下例为推荐写法函数
function Person() { this.name = name; this.age = age; this.friends = ["A","B"]; } //原型模式写法1,在默认prototype上补充 Person.prototype.sayName = function() { alert(this.name); } Person.prototype.startid = 0; //共享 //写法2,覆盖默认的prototype Person.prototype = { constructor : Person, // 注意覆盖写法应加入constructor属性 sayName: function(){ alert(this.name); } startid:0 }
全部对象共享Prototype域,而构造函数里添加的域是独立的。对象构造完之后若是再给prototype中的域赋值能够将其覆盖,注意不是删除,由于若是将本身新加的delete以后,prototyoe中的就又出现了。this
动态原型模式:在构造函数中解决原型的初始化,只有构造的第一个对象会触发if条件,填充Person的原型.net
function Person(name, age, job) { this.name = name; this.age = age; this.job = job; if (typeof this.sayName != "function") { // 检查一个属性就行 Person.prototype.sayName = fuction() { alert(this.name); } Person.prototype.startid = 0; } }
继承——利用原型链 (不能解决全部子类原型共用一个超类实例的问题,不推荐用)prototype
function SuperType() { this.property = true; } SuperType.prototype.getSuperValue = function() { return this.property; }; function SubType() { this.subproperty = false; } //继承 SubType.prototype = new SuperType(); SubType.prototype.getSubValue = function() { return this.subproperty; } var instance = new SubType();
可是,因为SubType没有重定义constructor,因此继承了SuperType的constructor。可是constructor不影响instanceof设计
借用构造函数: 不是new一个父类对象,而是调用构造函数向子类添加父类的域,因此子类没法访问父类的原型中的内容,不推荐使用指针
function SuperType() { this.colors = ["red","blue"]; } fuction SubType() { SuperType.call(this); // 借用构造函数,在子类中再构造一次父类 }
组合继承:调用两次父类构造函数,效率低,此方法子类的constructor也是错的
function SuperType(name) { this.name = name; this.colors = ["red","blue","green"]; } SuperType.prototype.sayName = function() { alert(this.name); }; function SubType(name, age) { SuperType.call(this,name); // 借用父类构造函数 this.age = age; } SubType.prototype = new SuperType(); //原型继承 SubType.prototype.sayAge = function() { alert(this.age); }
寄生组合式:推荐使用,用此函数替代组合继承的的 SubType.prototype = new SuperType();
// 书中写法,constructor在原型里 function object(o) { function F(){} F.prototype = o; return new F(); } function inheritPrototype(subType, superType) { var prototype = object(superType.prototype); //拷贝原型 prototype.constructor = subType; //添加constructor subType.prototype = prototype; //指定原型 } //网上的另外一个写法, 感受也是对的, 区别是constructor不在原型里。 SubType.prototype = SuperType.prototype; SubType.constructor = SubType;
有关prototype、constructor和__proto__的关系参考下面这篇文章,写的很清晰
闭包:定义在函数内的函数,内层函数拥有指向外层函数活动记录的指针,能够访问外层函数的变量。
私有权限:用闭包实现,有this的是公有权限,var的是非公有权限
function MyObject() { //私有变量和私有函数 var privateVariable = 10; function privateFunction() { return false; } //特权方法,外界可调用 this.publicMethod = function() { privateVariable++; return privateFunction(); } } var m = new MyObject();
静态私有:解决上述中函数不共享的问题,私有变量和prototype是共享的
(function(){ //私有 var privateVariable = 10; function privateFunction() { return false; } MyObject = function(value) { //函数中不带var的变量是全局变量 }; MyObject.prototype.publicMethod = function() { privateVariable++; return privateFunction(); }; })(); var m = new MyObject(value);