$(this) undefined 通过 bower 和 node 上的 requirejs

$(this) undefined via requirejs on bower and node

我正在尝试使用 requirejs 以模块化方法开发应用程序,并且只包含尽可能少的 jQuery 代码。我有一个基本的 SPA 应用 o.html:

<!doctype html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <title>jQuery Snippets</title>
    <script data-main="main-built" src="require.js"></script>
</head>
<body>
<div class="html">
    <p>this is p</p>
    <br />
    After break...
    <p>second p</p>
</div>
</body>
</html>

app.js:

define([ "jquery/core/init" ], function( $ ) {
     console.log( $(this) );
}); // not ok. Error message below:

main-built.js:483 Uncaught TypeError: Failed to set an indexed property on 'Window': Indexed property setter is not supported.

将 console.log 中的代码替换为 $('body') 有效,但 $(this)$(document) 无效。

完整错误:

main-built.js:483 Uncaught TypeError: Failed to set an indexed property on 'Window': Indexed property setter is not supported.
    at push (<anonymous>)
    at Function.makeArray (main-built.js:483)
    at jQuery.fn.init (main-built.js:3334)
    at main-built.js:10957
    at Object.execCb (require.js:5)
    at e.check (require.js:5)
    at enable (require.js:5)
    at e.init (require.js:5)
    at a (require.js:5)
    at Object.completeLoad (require.js:5)

build.js 是:

({
    baseUrl: ".",
    paths: {
        jquery: "bower_components/jquery/src/",
        sizzle: "bower_components/jquery/external/sizzle/dist/",
        require: "."
    },
    name: "app",
    out: "main-built.js"
})

节点:node r.js -o build.js optimize=none 和 运行 在浏览器上。

我期待浏览器控制台输出:

init [Window]

我还注意到 $('body') 输出:<body>...</body> 而不是:

init [body, prevObject: init(1), context: document, selector: "body"]

按照这个 2014 post

可以很容易地复制我的设置

有什么我遗漏的吗?

我不想包括整个 jquery 库,因为它在每个新版本中都变得越来越大。我只想获得我需要的模块。感谢任何有用的输入或推荐的替代解决方案。

提前致谢。

虽然我当然可以通过使用 $.call(Object, argument) 或在代码中的某处执行 Object.assign({}, object) 来更改 $(this) 的上下文,以操纵 [=64 的 $.fn.init(selector, context) =],我决定创建一个替代的 Vanilla 解决方案框架。

而且,虽然 jQuery 值得追求,但我构建了这个 自定义核心 jQuery 支持库。换句话说,这个框架模仿了 jQuery 语法中的所有内容,如最小代码示例所示。我相信这也是大多数开发人员需要的缺失手册,由于jQuery的流行度和搜索排名战,如今在互联网上几乎不可能搜索到。

OP中提到的目标是尝试只包含尽可能少的jQuery尽可能编写代码 根据需要使用 jQuery 代码段实施替代 解决方案,因为 jQuery 随着更新的版本和扩展以及大多数除了学习曲线之外,这些代码的性能开销相当大。

有了这个新的 CORE,我可以轻松地扩展对 jQuery 的支持,使用 $.fn.extend$.extend$.prototype.extend 以及未来需要时的用例,为一些基本例程做另一个插件或重新插入 $(function()})$(document.ready()}) 或实现其他自定义过滤器和 jQuery-like choress,其中一些我已经构建并从此代码中剥离例如事件处理程序和 $.ajax.

好消息是,我们甚至可以 重用已经构建的最喜欢的 jQuery 插件 而不必担心兼容性问题,因为 jQuery 的强大之处在于已经在我们手中了!核心还保留了我们最喜欢的点符号! :D

总的来说,无论何时构建最小的、可管理的、可重用的、模块化的 Javascript,以及构建在 缺少 Vanilla 学习曲线 和了解浏览器的工作原理,特别是因为 jQuery 的核心,即 $.extend 在这里得到了保留。这个库的一些机制(大约 2% 的代码)是从 jQuery 移植的,我计划在这个 CORE 之上构建我的项目,而不必担心许可证问题。

也就是说,我希望这对一些开发人员有所帮助。我正在向麻省理工学院授权此代码。

(function(){
    "use strict";
    var _, context = {}, version = 1.0;
    _ = (function(selector){
        _ = function( selector, context ) {
            if(this instanceof _ == false) {
                return new _.fn.init(selector, context);
            };

            return new _.fn.init( selector, context );
        };

        _.fn = _.prototype = {
            _: version,
            constructor: _,
            length : 0
        }

        _.extend = _.fn.extend = function() {
            var target = arguments[ 0 ] || {}, options, copy,
                i = 1,
                length = arguments.length;

            // Extend _ itself if only one argument is passed
            if ( i === length ) {
                target = this;
                i--;
            }

            for ( ; i < length; i++ ) {
                if ( ( options = arguments[ i ] ) != null ) {
                    for ( name in options ) {
                        copy = options[ name ];

                        target[ name ] = copy;
                    }
                }
            }
            return target;
        };

        _.selectors = function(el){
            var elem = [];
            for(let i = 0; i<el.length; i++){
                elem.push(el[i]);
            }
            return elem;
        }

        _.prototype.self = function(){
            this.object = this;

            this.selectors = document.querySelectorAll(selector).length &&  document.querySelectorAll(selector).length == 1

                ? document.querySelector(selector)
                : document.querySelectorAll(selector).length == 0 
                    ? '' 
                    : Array.prototype.slice.call(document.querySelectorAll(selector));

                return this;
        }

        _.prototype.html = function(arg){ // return only the first element

            if(arguments.length==0)
                return this.element.innerHTML;
            else
                return this.element.innerHTML = arg;
        };

        _.prototype.text = function(arg){ // return only the first element
            return this.element.innerText;
        };

        var root_, _quickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/,
        init = _.fn.init = function( selector, context, root ) {

            if ( !selector ) {
                return this;
            }

            root = root || root_;
            this.selector = selector;
            this.element = null;
            var self = this, el = [];

            if(arguments.length > 0){

                if(typeof selector === 'object'){

                    if(selector == document || selector == window){
                        if(selector===window) {
                            console.log(this);
                            return Array(window);
                        } else if(selector == document){
                            return _('html');
                        }

                        return _('body');
                    } else {
                        if(selector instanceof Element){

                            this.html = function(text){
                                if(arguments.length>0)
                                    return selector.innerHTML = text;
                                else 
                                    return selector.innerHTML;
                            }
                            this.children = _.map(selector);

                            return this;
                        }
                    }
                }

                switch (selector) {
                    case '<':
                    var matches = selector.match(/<([\w-]*)>/);
                    if (matches === null || matches === undefined) {
                        throw 'Invalid Selector / Node';
                        return false;
                    }
                    var nodeName = matches[0].replace('<', '').replace('>', '');
                    this.element = document.createElement(nodeName);
                    break;
                    default:
                    this.element = document.querySelector(selector);
                }

                var els = document.querySelectorAll(selector);

                for (var ie = 0; ie < els.length; ie++) {
                    el.push(els[ie]);
                }

                this.children = el;
                _.prototype.elements = (typeof selector === 'object') 
                    ? new Array(selector) 
                        : document.querySelectorAll(selector);
            }

            this[0] = this.element;

            return this;
        };
        // Give the init function the _ prototype for later instantiation
        init.prototype = _.fn;
        // Initialize central reference
        // root_ = _( document ); // optional
        return _;

    })();
    _.map = function (element) {
        return Array.prototype.map.call([element], (function (node) {
            return node;
        }));
    };
    _.each = _.prototype.each = function(r, cb) {  // faster than forEach!
      for (var i = 0, l = r.length; i < l; i++) {
        cb.call(r[i], i);
      }
      return this;
    }
    window._ = _;

    window.$ === undefined && (window.$ = _); // Own the $! :D

    return _;

}).call(this);

$.extend({
    hello : function(){
        console.log('$.extending hello');
    }
});

$.hello();

$('body').extend({
    hello : function(){
        console.log('$.fn.extending hello');
        return this;
    }
}).hello();

$.fn.extend({
    find : function(el,cb){
        var context = null, collection = [], outer = this.elements;
        this ["prevObject"] = _.selectors(this.elements);
        this.selector = (this.selector + ' '+ el).toString();
        this.this = this ["prevObject"];
        if(outer.length>0)
            for(var i=0; i<outer.length; i++) {
                collection = collection.concat(Array.prototype.slice.call(outer[i].querySelectorAll(el)));
            }

        else
            collection.push(this.element.querySelectorAll(el));
        if(arguments.length>1){
            this.childName = collection[0].localName;
            this.collection = collection;
            this.parentName = this.elements[0].localName;
            context = this;
            this.context = Object.assign({}, context);
            cb.call(this.parentName, this.childName, collection);
        } else {
            this[0] = collection;
        }
        
        return this;
    }
})
<html>
<head><title>Localizing this</title>
</head>
<body>
    <div class="test">Localizing <b>$(this)</b> <i>by unlearning <b>jQuery</b></i> with <u>6.8 kb unminified custom <b>CORE</b> extensible library</u>:<br />
        <p style="color:magenta;">I want to do $('body').find('p');</p>
        <p>this is paragraph 2</p>
    </div>
    <div id="div2">
        <span>I am span</span>
        <p> I am p</p>
        <a href="#">I am link</a><br /><br />
    </div>
    <div>Importance of using <strong style="font-size: 15px; color:#333;">$(this)</strong> after finding <b style="color:purple;">p</b>:
        <pre style="color:indigo;">
            <quote style="background: #eee;">
    $(this);
    $('div').find('p', function(i,collection){
        $.each(collection, function(i){
            console.log($(this).html());
            console.log($(this).html("Success!!!"));
            console.log($(this).children[0].style);
        });
    }); 
            </quote>
        <pre>
    </div>
</body>
</html>