浅谈javascript的原型继承_javascript技巧

js教程评论1.4K views阅读模式

请看源码:

复制代码 代码如下:

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;

}

}

企鹅博客
  • 本文由 发表于 2020年9月27日 03:23:04
  • 转载请务必保留本文链接:https://www.qieseo.com/423804.html

发表评论