Partially inheriting jQuery prototype

I want to use Coffeescript to create a UIObject class. This class should inherit from jQuery, so that UIObject instances can be used as if they were created using jQuery.

class UIObject isObject: (val) -> typeof val is "object" constructor: (tag, attributes) -> @merge jQuery(tag, attributes), this @UIObjectProperties = {} merge: (source, destination) -> for key of source if destination[key] is undefined destination[key] = source[key] else if @isObject(source[key]) @merge(source[key], destination[key]) return 

It partially works. Consider the Foobar class below:

 class Foobar extends UIObject constructor: -> super("<h1/>", html: "Foobar") 

$("body").append(new Foobar) working fine. BUT: (new Foobar) .appendTo ("body") places the tag, but also raises RangeError: Maximum call stack size exceeded .

Was it just a bad idea to inherit from jQuery? Or is there a solyur?

For those who don't know CoffeeScript, the JavaScript source code:

  var Foobar, UIObject; var __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor; child.__super__ = parent.prototype; return child; }; UIObject = (function () { UIObject.prototype.isObject = function (val) { return typeof val === "object"; }; function UIObject(tag, attributes) { this.merge(jQuery(tag, attributes), this); this.UIObjectProperties = {}; } UIObject.prototype.merge = function (source, destination) { var key; for (key in source) { if (destination[key] === void 0) { destination[key] = source[key]; } else if (this.isObject(source[key])) { this.merge(source[key], destination[key]); } } }; return UIObject; })(); Foobar = (function () { __extends(Foobar, UIObject); function Foobar() { Foobar.__super__.constructor.call(this, "<h1/>", { html: "Foobar" }); } return Foobar; })(); 
+4
source share
1 answer

It's really hard to do (but creative!), Since both the jQuery and CoffeeScript classes have their own ideas about the .constructor() method.

In jQuery 1.6.4 (the one used today on the CoffeeScript homepage), line 246 of jQuery itself creates an infinite recursion in this line of code:

 var ret = this.constructor(); 

this here points to your constructor, but jQuery expects it to point to itself. Your @merge() method will not replace the constructor correctly. There is even a hacker output, change your @merge() method to:

 merge: (source, destination) -> for key of source if destination[key] is undefined destination[key] = source[key] else if @isObject(source[key]) @merge(source[key], destination[key]) @constructor = jQuery 

Everyday testing at Try coffeescript showed that it works, but I would fear that weird effects might come later, so if you continue this approach, take the test.

0
source

Source: https://habr.com/ru/post/1383072/


All Articles