var person = {name: "tree",age: 25,say: function(){console.log("I"m tree.")}};var cloneTree = Object.create(person);console.log(cloneTree);function Person(name, age){this.name = name;this.age = age;}var p = new Person("tree", 25) 实际上,当一个函数对象呗创建时,Function构造器产生的函数对象会运行类似这样的一些代码:this.prototype = {constructor: this} 新的函数对象被赋予一个prototype属性,它的值是一个包含constructor属性且属性值为该新函数的对象。当对一个函数使用new运算符时,函数的prototype的属性的值被作为原型对象来克隆出新对象。如果new运算符是一个方法,它的执行过程如下:Function.prorotype.new = function() {//以prototype属性值作为原型对象来克隆出一个新对象var that = Object.create(this.prorotype);//改变函数中this关键指向这个新克隆的对象var other = this.apply(that, arguments);//如果返回值不是一个对象,则返回这个新克隆对象return (other && typeof other === "object") ? other : that;} 从上面可以看出,虽然使用new运算符调用函数看起来像是使用模板实例化的方式来创建对象,但本质还是以原型对象来克隆出新对象。function Person(name, age) {this.name = name;this.age = age;};Person.prototype.say = function(){console.log("Hello, I"m " + this.name);};继承function Person(name, age) {this.name = name;this.age = age;};Person.prototype.say = function(){console.log("Hello, I"m " + this.name);};function Employee(name, age, major) {Person.apply(this, arguments);this.major = major;};Employee.prototype = Object.create(Person.prototype);Employee.prorotype.constructor = Employee;Employee.prorotype.sayMajor = function(){console.log(this.major);}
所以大多数语言并不支持多继承,如Java支持单继承+接口的形式。JavaScript并不支持接口,要在一个不支持接口的语言上去模拟接口怎么办?答案是著名的鸭式辨型。放到实际代码中就是混入(mixin)。原理很简单:
function mixin(t, s) {for (var p in s) {t[p] = s[p];}} 值得一提的是dojo利用MRO(方法解析顺序(Method Resolution Order),即查找被调用的方法所在类时的搜索顺序)方式解决了多继承的问题。 (function(global) {var define = global.define;if (define && define.amd) {define([], function(){return O;});} else {global.O = O;}function O(){};O.derive = function(sub) {debugger;var parent = this;sub = sub ? sub : {};var o = create(parent);var ctor = sub.constructor || function(){};//如何调用父类的构造函数?var statics = sub.statics || {};var ms = sub.mixins || [];var attrs = sub.attributes || {};delete sub.constructor;delete sub.mixins;delete sub.statics;delete sub.attributes;//处理继承关系ctor.prototype = o;ctor.prototype.constructor = ctor;ctor.superClass = parent;//利用DefineProperties方法处理Attributes//for (var p in attrs) {Object.defineProperties(ctor.prototype, attrs);//}//静态属性mixin(ctor, statics);//混入其他属性和方法,注意这里的属性是所有实例对象都能够访问并且修改的mixin(ctor.prototype, sub);//以mixin的方式模拟多继承for (var i = 0, len = ms.length; i < len; i++) {mixin(ctor.prototype, ms[i] || {});}ctor.derive = parent.derive;//_super函数ctor.prototype._super = function(f) {debugger;return parent.prototype[f].apply(this, Array.prototype.slice.call(arguments, 1));}return ctor;}function create(clazz) {var F = function(){};F.prototype = clazz.prototype;//F.prototype.constructor = F; //不需要return new F();};function mixin(t, s) {for (var p in s) {t[p] = s[p];}}})(window);类创建方式如下:var Person = O.derive({constructor: function(name) {//构造函数this.setInfo(name);},statics: {//静态变量declaredClass: "Person"},attributes: {//模拟C#中的属性Name: {set: function(n) {this.name = n;console.log(this.name);},get: function() {return this.name + "Attribute";}}},share: "asdsaf",//变量位于原型对象上,对所有对象共享setInfo: function(name) {//方法this.name = name;}});var p = new Person("lzz");console.log(p.Name);//lzzAttributeconsole.log(Person);继承:var Employee = Person.derive({//子类有父类派生constructor: function(name, age) {this.setInfo(name, age);},statics: {declaredClass: "Employee"},setInfo: function(name, age) {this._super("setInfo", name);//调用父类同名方法this.age = age;}});var e = new Employee("lll", 25);console.log(e.Name);//lllAttributeconsole.log(Employee);以上就是本文的全部内容,希望对大家的学习有所帮助。