javascript - sortable - addeventlistener drop error "TypeError no capturado: invocación ilegal"
sortable js (2)
El error "Invocación ilegal" significa que intenta llamar a una función invocable con el contexto incorrecto, siendo el contexto el objeto al que se llama el método. Déjame desglosar la console.log
:
console.log(element.__proto__.ondrop)
Aquí está intentando registrar el element.__proto__.ondrop
. Primero, déjame explicar el element.__proto__
. La propiedad de acceso en cada objeto, Object.prototype.__proto__
es una propiedad de acceso que apunta al prototipo de ese objeto y se usa para resolver los métodos en la cadena de búsqueda. Por ejemplo:
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
Aquí, __proto__
de una instancia se refiere al prototype
del constructor que construyó la instancia. Ahora, en su caso, el __proto__
de un elemento del DOM sería algo HTMLDivElement
al prototipo de HTMLDivElement
o algo más, dependiendo del tipo de elemento que sea. A los efectos de esta respuesta, diremos que es un div
.
Ahora, cuando intenta acceder al ondrop
de propiedad del prototipo HTMLDivElement
, recibe una invocación ilegal porque está intentando acceder de ondrop
estática desde el prototipo HTMLDivElement
, ¡no es un elemento div
real ! Esto lleva al "contexto incorrecto" porque está intentando llamar al HTMLDivElement.prototype
de HTMLDivElement.prototype
en HTMLDivElement.prototype
, ¡no a un div
del DOM!
Para "arreglar esto", no acceda a la tecla __proto__
. Si desea acceder a la propiedad ondrop
del elemento, simplemente haga element.ondrop
.
Creo un nuevo objeto por función y creo un método sortable
para usar, pero que tiene un error en la función de devolución de llamada
;"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''
});
<!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>
Y esto es un error: Uncaught TypeError: Illegal invocation
Eso estaba en la función goesCallback
cuando arrastro .sorterItem
y lo .sorterItem
caer. Puede matar el navegador.
Entonces, en el método console.log(element.__proto__.ondrop)
tengo console.log(element.__proto__.ondrop)
para ver Error en alguna línea.
¿Cómo arreglar este error?
gracias a todos.
No puede hacer console.log(element.__proto__.ondrop)
ya que ondrop es una propiedad de acceso.
¿Propiedades del Accesorio? Con referencia a esta SO Respuesta
Una propiedad de acceso es aquella que se define en términos de getters y setters, no como un valor almacenado en el que se podría escribir. El "par de funciones de acceso" denota el getter y la función setter.
Ver también esta respuesta
Así que, básicamente, al llamar a console.log(element.__proto__.ondrop)
está invocando la función ondrop
del elemento ondrop
sin este contexto apropiado, lo que da como resultado un error de Invocación Ilegal .
Ejemplo de código
Un ejemplo de código de JavaScript para ilustrar el punto
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
Así que cuando llamas a console.log(element.__proto__.ondrop)
esencialmente estás activando el getter ondrop
sin un contexto válido .
Actualizar:
Supongo que lo que quería hacer era inspeccionar por qué los Drag-events no se activaban y terminaba colocando console.log(element.__proto__.ondrop)
que, como ya se ha respondido, provocó el error de IllegalInvocation
, lo que dio como resultado un clase de error totalmente diferente a la que estabas tratando de depurar
El motivo por el que los eventos de arrastre no se activan es la llamada de función dentro de los manejadores Event.preventDefault () , que cita de MDN
El método preventDefault () de la interfaz de eventos le dice al agente de usuario que si el evento no se controla, su acción predeterminada no debería tomarse como lo haría normalmente.
En su caso, la acción predeterminada significa la funcionalidad relacionada con Arrastrar, que (¡por descuido!) Impide la ejecución.
Le sugiero que lea más acerca de HTML5 arrastrar y soltar API en MDN.