Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Inherit all methods from Array.prototype! #24

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

exside
Copy link

@exside exside commented Jul 1, 2019

If we initiate the ki object by inheriting from Array.prototype, we can save ourselves some extensions because we can already natively use ALL array methods on our collections (they of course need to be wrapped again in $() to make them ki collections, which requires that the constructor (i function) can deal with arrays as input, which is one of the additions to the i function here, others are:

  • DOM node creation like jQuery by passing HTML-tags, see other PR
  • $() now returns a documentFragment (nice to construct HTML in memory and then append it to the DOM) instead of a useless empty collection

I know, this all adds valuable bytes (~80 bytes to be exact), but we can now also remove the splice and length props as they are inherited by Array.prototype and I think the huge gain in functionality out of the box would justify the increase in size.

the native array methods that collide with jQuery methods, like find() for example, can still be easily overwritten with an extension like this:

$.fn.find = function(a){
	var r = [];
	this.each(function(e) {
		r = r.concat(this.slice.call(e.querySelectorAll(a)));
	});
	return $(r);
};

which might be appropriate if we try to mirror jQuery, but in other scenarios the native .find() might be enough, who knows... in my opinion that's the nice thing about ki =), it can be extended as needed without having to define a bunch of stuff we might need or not...

If we initiate the ki object by inheriting from `Array.prototype`, we can save ourselves some extensions because we can already natively use ALL array methods on our collections (they of course need to be wrapped again in `$()` to make them ki collections, which requires that the constructor (`i` function) can deal with arrays as input, which is one of the additions to the i function here, others are:

- DOM node creation like jQuery by passing HTML-tags, see other PR
- `$()` now returns a documentFragment (nice to construct HTML in memory and then append it to the DOM) instead of a useless empty collection

I know, this all adds valuable bytes, but we can now also remove the `splice` and `length` props as they are inherited by `Array.prototype` and I think the huge gain in functionality out of the box would justify the increase in size.

the native array methods that collide with jQuery methods, like `find()` for example, can still be easily overwritten with an extension like this:

```
$.fn.find = function(a){
	var r = [];
	this.each(function(e) {
		r = r.concat(this.slice.call(e.querySelectorAll(a)));
	});
	return $(r);
};
```

which might be appropriate if we try to mirror jQuery, but in other scenarios the native `.find()` might be enough, who know, that's the nice thing about ki =), it can be extended as needed without having to define a bunch of stuff we might need or not...
@exside exside mentioned this pull request Jul 1, 2019
@pwFoo
Copy link

pwFoo commented Aug 12, 2019

ki.js looks unmaintained, but I found https://github.com/edwinm/miq/blob/master/miq.js?

@pwFoo
Copy link

pwFoo commented Aug 12, 2019

Hi @exside just for me to understand the code...

Would it possible to explain / convert to readable the i function?

  function i(a) {
    c.push.apply(this, a && a.nodeType ? [a] : a && Array.isArray(a) ? a : '' + a === a ? ( a[0] === '<' && a[a.length - 1] === '>' ? [b.createElement(a.replace(/^<(\w+)\s*?\/?>[^\n\r\S]*(?:$|<\/\1>)/, '$1'))] : b.querySelectorAll(a) ) : [b.createDocumentFragment()]);
  }

Interested in the original ki.js and the inheriting from Array.prototype part, because I'm new with JavaScript.

ki.js Outdated
@@ -10,7 +10,7 @@
* a = selector, dom element or function
*/
function i(a) {
c.push.apply(this, a && a.nodeType ? [a] : '' + a === a ? b.querySelectorAll(a) : e)
c.push.apply(this, a && a.nodeType ? [a] : a && Array.isArray(a) ? a : '' + a === a ? ( a[0] === '<' && a[a.length - 1] === '>' ? [b.createElement(a.replace(/^<(\w+)\s*?\/?>[^\n\r\S]*(?:$|<\/\1>)/, '$1'))] : b.querySelectorAll(a) ) : [b.createDocumentFragment()]);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

a[0] === '<' && a[a.length - 1] === '>' is longer than /^<[^\0]+>$/.test(a)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Absolutely right, thanks! Updated the PR

Add suggestion to shorten check for tag-string input
@exside
Copy link
Author

exside commented Aug 27, 2019

@pwFoo

to split the init function a bit apart:

// if the input of the init function a single DOM element node, wrap it in an array
a && a.nodeType ? [a] :
// if the input is already an array, leave it as is
a && Array.isArray(a) ? a : 
// check if the input is a string
'' + a === a ?
// and if so, does it look like an HTML tag, for example '<div>'
( /^<[^\0]+>$/.test(a) ?
// if so, strip everything except the tag name so document.createElement() can understand it
[b.createElement(a.replace(/^<(\w+)\s*?\/?>[^\n\r\S]*(?:$|<\/\1>)/, '$1'))] : 
// if the input is a string but not a tag, pass it as a selector to document.querySelectorAll()
b.querySelectorAll(a) ) : 
// and if the init function is called "empty", return a document fragment, e.g. $() will trigger that
[b.createDocumentFragment()]);

and yes, miq is nice and was the inspiration to inherit from the array prototype! I do like the modularity of ki better though...miq, even though very small in size, already includes stuff I don't need ever... and regarding being "maintained": AFAIK it was just an experiment to make the smallest possible "jQuery like" library, never intended for anything serious =)...but it works quite well as a little dom helper for me...

if you look for something more modern, also have a look at https://github.com/biancojs/bianco

@dciccale
Copy link
Owner

dciccale commented Nov 30, 2019

hi @exside what is gained exactly by extending from Array.prototype? what use-cases would this cover? It would help to see some real-world examples :)
I think we could merge it if it has enough good impact in the final result
Thanks

// for some reason is needed to get an array-like
// representation instead of an object
splice: c.splice
}},
}
Copy link

@boehs boehs Nov 3, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
}
});

Otherwise this errors

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks good, aside from this

@boehs
Copy link

boehs commented Nov 3, 2021

Upon evaluating this pr all seems well except the fix above, @dciccale this can be merged and given the other issue the use is obvious.

I have been able to find no reproduction's and massive benefit


If you are looking for a maintainer for this I will do it by the way, interested if min can be done by github actions, more tests, and making it a ES6 module

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants