Heim  >  Artikel  >  Web-Frontend  >  浅谈javascript的原型继承_javascript技巧

浅谈javascript的原型继承_javascript技巧

WBOY
WBOYOriginal
2016-05-16 17:51:351056Durchsuche

请看源码:

复制代码 代码如下:

function clone(o) {
var F = function(){};
F.prototype = o;
return new F();
}

首先看ext(4.1的1896行开始)的原型式继承。
复制代码 代码如下:

var TemplateClass = function(){};
var ExtObject = Ext.Object = {
chain: function (object) {
TemplateClass.prototype = object;
var result = new TemplateClass();
TemplateClass.prototype = null;
return result;
}
}

这里清除了object的prototype。
再看一下jquery是怎么玩的继承。
复制代码 代码如下:

var jQuery = function( selector, context ) {
return new jQuery.fn.init( selector, context, rootjQuery );
};
-----------------------
jQuery.fn = jQuery.prototype = {
constructor: jQuery,
init: function( selector, context, rootjQuery ) {
-----------------------
}
}
-------------------
jQuery.fn.init.prototype = jQuery.fn;

jquery玩的就比较高,借助jQuery.fn.init来完成,但是思路一样。
司徒正美的mass里也有类似的继承,在lang_fix.js里面第17行:
复制代码 代码如下:

create: function(o){
if (arguments.length > 1) {
$.log(" Object.create implementation only accepts the first parameter.")
}
function F() {}
F.prototype = o;
return new F();
}

查看了一下es5的官方,找到了他的兼容补丁:
复制代码 代码如下:

// ES5 15.2.3.5
// http://es5.github.com/#x15.2.3.5
if (!Object.create) {
Object.create = function create(prototype, properties) {
var object;
if (prototype === null) {
object = { "__proto__": null };
} else {
if (typeof prototype != "object") {
throw new TypeError("typeof prototype["+(typeof prototype)+"] != 'object'");
}
var Type = function () {};
Type.prototype = prototype;
object = new Type();
// IE has no built-in implementation of `Object.getPrototypeOf`
// neither `__proto__`, but this manually setting `__proto__` will
// guarantee that `Object.getPrototypeOf` will work as expected with
// objects created using `Object.create`
object.__proto__ = prototype;
}
if (properties !== void 0) {
Object.defineProperties(object, properties);
}
return object;
};
}

上面的代码考虑的就比较全面,但是需要另外引入Object.defineProperties的补丁才行,源码相对就比较多了。
复制代码 代码如下:

// ES5 15.2.3.6
// http://es5.github.com/#x15.2.3.6
// Patch for WebKit and IE8 standard mode
// Designed by hax
// related issue: https://github.com/kriskowal/es5-shim/issues#issue/5
// IE8 Reference:
// http://msdn.microsoft.com/en-us/library/dd282900.aspx
// http://msdn.microsoft.com/en-us/library/dd229916.aspx
// WebKit Bugs:
// https://bugs.webkit.org/show_bug.cgi?id=36423
function doesDefinePropertyWork(object) {
try {
Object.defineProperty(object, "sentinel", {});
return "sentinel" in object;
} catch (exception) {
// returns falsy
}
}
// check whether defineProperty works if it's given. Otherwise,
// shim partially.
if (Object.defineProperty) {
var definePropertyWorksOnObject = doesDefinePropertyWork({});
var definePropertyWorksOnDom = typeof document == "undefined" ||
doesDefinePropertyWork(document.createElement("div"));
if (!definePropertyWorksOnObject || !definePropertyWorksOnDom) {
var definePropertyFallback = Object.defineProperty;
}
}
if (!Object.defineProperty || definePropertyFallback) {
var ERR_NON_OBJECT_DESCRIPTOR = "Property description must be an object: ";
var ERR_NON_OBJECT_TARGET = "Object.defineProperty called on non-object: "
var ERR_ACCESSORS_NOT_SUPPORTED = "getters & setters can not be defined " +
"on this javascript engine";
Object.defineProperty = function defineProperty(object, property, descriptor) {
if ((typeof object != "object" && typeof object != "function") || object === null) {
throw new TypeError(ERR_NON_OBJECT_TARGET + object);
}
if ((typeof descriptor != "object" && typeof descriptor != "function") || descriptor === null) {
throw new TypeError(ERR_NON_OBJECT_DESCRIPTOR + descriptor);
}
// make a valiant attempt to use the real defineProperty
// for I8's DOM elements.
if (definePropertyFallback) {
try {
return definePropertyFallback.call(Object, object, property, descriptor);
} catch (exception) {
// try the shim if the real one doesn't work
}
}
// If it's a data property.
if (owns(descriptor, "value")) {
// fail silently if "writable", "enumerable", or "configurable"
// are requested but not supported
/*
// alternate approach:
if ( // can't implement these features; allow false but not true
!(owns(descriptor, "writable") ? descriptor.writable : true) ||
!(owns(descriptor, "enumerable") ? descriptor.enumerable : true) ||
!(owns(descriptor, "configurable") ? descriptor.configurable : true)
)
throw new RangeError(
"This implementation of Object.defineProperty does not " +
"support configurable, enumerable, or writable."
);
*/
if (supportsAccessors && (lookupGetter(object, property) ||
lookupSetter(object, property)))
{
// As accessors are supported only on engines implementing
// `__proto__` we can safely override `__proto__` while defining
// a property to make sure that we don't hit an inherited
// accessor.
var prototype = object.__proto__;
object.__proto__ = prototypeOfObject;
// Deleting a property anyway since getter / setter may be
// defined on object itself.
delete object[property];
object[property] = descriptor.value;
// Setting original `__proto__` back now.
object.__proto__ = prototype;
} else {
object[property] = descriptor.value;
}
} else {
if (!supportsAccessors) {
throw new TypeError(ERR_ACCESSORS_NOT_SUPPORTED);
}
// If we got that far then getters and setters can be defined !!
if (owns(descriptor, "get")) {
defineGetter(object, property, descriptor.get);
}
if (owns(descriptor, "set")) {
defineSetter(object, property, descriptor.set);
}
}
return object;
};
}
// ES5 15.2.3.7
// http://es5.github.com/#x15.2.3.7
if (!Object.defineProperties) {
Object.defineProperties = function defineProperties(object, properties) {
for (var property in properties) {
if (owns(properties, property) && property != "__proto__") {
Object.defineProperty(object, property, properties[property]);
}
}
return object;
};
}

EcmaScript6的类继承。
复制代码 代码如下:

class module extends Base {
constructor() {
}
}

越玩越像java了,不过es6很多浏览器还不支持。
最后推荐的写法:
复制代码 代码如下:

if (!Object.create) {
Object.create = function create(o) {
var F = function(){};
F.prototype = o;
var result = new F();
F.prototype = null;
return result;
}
}
Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn