addeventlistener drop error" Uncaught TypeError:非法调用"

时间:2017-06-05 05:04:53

标签: javascript callback drag-and-drop html5sortable

我按功能创建新的Object,并创建sortable方法来使用,但是在回调函数上有错误



;"use strict";
(function(){
    function libJS(){};

    libJS.prototype = {
        loopElement : function(element, options, callback){
            var libObj = this;
            var goesCallback = function(element, options, callback){
                if (!!callback && libObj.isFunction(callback)) callback(element, options);
            };

            if (libObj.isElement(element)) goesCallback(element, options, callback);
            else if (libObj.isString(element) && /^(\.|\#)[\w\d\-_]+$/g.test(element)){
                if (/^\./g.test(element)){
                    element = document.getElementsByClassName(element.replace('.', ''));
                    var length = element.length || 0, i;
                    for(i = 0; i < length; i++) goesCallback(element[i], options, callback);
                }else{
                    element = document.getElementById(element.replace('#', ''));
                    if (!!element) goesCallback(element, options, callback);
                }
            }
        },

        isElement : function(element){
            // code check
            var f=(typeof HTMLElement === 'object' || false);
                f=(f && element instanceof HTMLElement);
                f=(f||(typeof element === 'object' && element.nodeType===1 && typeof element.nodeName === 'string'));
		    return f;
        },

        isString : function(str){
            // code check
            return true;
        },

        isObject : function(obj){
            // code check
            return true;
        },

        isFunction : function(func){
            // code check
            return true;
        },

        token : function(length){
            // create token
            return 'random_string';
        },

        sortable : function(options){
            if ('draggable' in document.createElement('span')){
                var libObj = this;
                if (libObj.isObject(options)){
                    libObj.loopElement(options.element, options, function(element, options){
                        element.style.position = 'relative';
                        var childNodes = element.childNodes,
                            length = childNodes.length || 0, x;
                        for (x = 0; x < length; x++){
                            var item = childNodes[x];
                            if (item.nodeName !== '#text'){
                                item.id = 'libJS-' + libObj.token(12);
                                item.draggable = true;
                                item.style.cursor = 'pointer';
                                item.style.transition = 'all 0.5s ease';
                                item.addEventListener('dragstart', function(event){
                                    event.preventDefault();
                                    // some code
                                });
                            }
                        }
                        element.addEventListener('dragover', function(event){
                            event.preventDefault();
                        });
                        element.addEventListener('drop', function(event){
                            event.preventDefault();
                        });
                        console.log(element.__proto__.ondrop); // View Error
                    });
                }
            }else throw 'ERROR: libJS.sortable(): this browser not support drag and drop event!';
        }
    };
    window.libJs = new libJS();
})();

libJs.sortable({
   element : '.sorter'
});
&#13;
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <title>Test</title>
        <style type="text/css">
            *{
                box-sizing: border-box;
            }
            .sorter{
                border: 1px solid green;
                padding: 10px;
            }
            .sorter:after{
                display: block;
                content: '';
                clear: both;
            }
            .sorterItem{
                display: inline-block;
                float: left;
                width: 70px;
                height: 70px;
                margin-right: 10px;
                margin-bottom: 10px;
            }
            .sorterItem img{
                display: block;
                max-width: 100%;
                max-height: 100%;
                min-width:100px;
                min-height:100px;
            }
        </style>
    </head>
    <body>
        <div class="sorter">
            <div class="sorterItem">
                <img src="/data/upload/noimage.jpg" />
            </div>
            <div class="sorterItem">
                <img src="/data/upload/noimage.jpg" />
            </div>
            <div class="sorterItem">
                <img src="/data/upload/noimage.jpg" />
            </div>
            <div class="sorterItem">
                <img src="/data/upload/noimage.jpg" />
            </div>
            <div class="sorterItem">
                <img src="/data/upload/noimage.jpg" />
            </div>
            <div class="sorterItem">
                <img src="/data/upload/noimage.jpg" />
            </div>
        </div>
    </body>
</html>
&#13;
&#13;
&#13;

这是一个错误:Uncaught TypeError: Illegal invocation

当我拖动goesCallback并放弃它时,这是.sorterItem函数。它可以杀死浏览器。

因此,在sortable方法中我console.log(element.__proto__.ondrop)可以在某行查看错误。

如何解决此错误?

谢谢大家。

2 个答案:

答案 0 :(得分:5)

你不能console.log(element.__proto__.ondrop),因为ondrop是一个访问者属性。

访问者属性?参考此SO Answer

  

访问者属性是根据getter和setter定义的属性,而不是可能写入的存储值。 “配对函数对”表示getter和setter函数。

另见this answer

所以基本上通过调用console.log(element.__proto__.ondrop)来调用元素的ondrop getter函数而没有正确的this context会导致Illegal Invocation错误。

代码示例
一个javascript代码示例来说明要点

var Person = {
  firstname: "John",
  lastname: "Doe",
  get fullname() {
    return this.firstname + " " + this.lastname
  },
  set fullname(name) {
    this.firstname = name.split(' ')[0]
    this.lastname = name.split(' ')[1]
  }
}

console.log(Person.fullname) // will trigger the getter function 'fullname'

Person.fullname = "Jane Doe" // will trigger the setter function 'fullname'

console.log(Person.fullname) // logs Jane Doe

因此,当您致电console.log(element.__proto__.ondrop)时,您实际上是在没有有效上下文的情况下触发ondrop获取者。

更新

我想你想要做的是检查为什么Drag-events没有被触发你最后放了一个console.log(element.__proto__.ondrop),因为它已经被回答,导致IllegalInvocation错误,结果在一个完全不同的错误类别,然后是你试图调试的那个!

您的Drag事件未触发的原因是处理程序Event.preventDefault()内的函数调用,引自MDN

  

Event接口的preventDefault()方法告诉用户代理,如果事件未处理,则不应采取其默认操作。

在您的情况下,默认操作表示与拖动相关的功能,您(无意中)阻止执行!

我建议您在MDN上阅读有关HTML5 Drag and Drop API的更多信息。

答案 1 :(得分:3)

错误&#34;非法调用&#34;表示您尝试使用错误的上下文调用可调用函数,上下文是调用该方法的对象。让我分解console.log

console.log(element.__proto__.ondrop)

在这里,您尝试记录element.__proto__.ondrop。首先,让我解释element.__proto__。每个对象Object.prototype.__proto__上的访问器属性是一个访问器属性,指向该对象的原型,用于解析查找链中的方法。例如:

&#13;
&#13;
function Person(name) { //This is a constructor function
  this.name = name; //Set the name to be part of the instance
} 
Person.prototype.sayName = function() { //A function on the prototype
  console.log(this.name);               //and is part of the instance
}

const bob = new Person("Bob");
console.log(bob.__proto__); //The __proto__ property refers to `Person.prototype`
                            //and will log the `Person.prototype` object
&#13;
&#13;
&#13;

这里,实例的__proto__引用构造实例的构造函数的prototype。现在,在您的情况下,来自DOM的元素的__proto__将是HTMLDivElement或其他原型的行,具体取决于它是什么类型的元素。出于这个答案的目的,我们会说它是div

现在,当您尝试访问ondrop原型的HTMLDivElement属性时,您会收到非法调用,因为您正在尝试访问{{1来自ondrop原型的静态,而非实际的HTMLDivElement元素!这导致了错误的背景&#34;因为您试图在div上调用访问者,而不是来自DOM的HTMLDivElement.prototype

要解决此问题&#34;,请勿访问div密钥。如果您想访问元素的__proto__属性,只需执行ondrop