2016-11-15 1 views
1

Вы можете изменить поведение класса Leaflet.js на including a mixin.Изменение поведения класса Leaflet с помощью include()

Учебник Extending Leaflet: Class Theory говорит:

Если класс уже определен, существующие свойства/методы могут быть переопределены, или новые могут быть добавлены с помощью .include():

Однако при попытке сделать это, я получаю ошибку Maximum call stack size exceeded.

var DemoClass = L.Class.extend({ 
 
    value: 42, 
 
    demoMethod: function() { 
 
    return this.value; 
 
    } 
 
}); 
 

 
DemoClass.include({ 
 
    demoMethod: function() { 
 
    return DemoClass.prototype.demoMethod.call(this) * 2; 
 
    }, 
 
    secondMethod: function() { 
 
    return this.value; 
 
    } 
 
}); 
 

 
var instance = new DemoClass(); 
 
console.log("value=" + instance.value); 
 
console.log("secondMethod()=" + instance.secondMethod()); 
 
console.log("demoMethod()=" + instance.demoMethod()); // gives a call stack exceeded
<script src="https://unpkg.com/[email protected]1/dist/leaflet.js"></script>

Если это уместно, фактический код перекрывая L.Marker.onAdd().

ответ

1

Попробуйте изолировать функцию базы:

var DemoClass = L.Class.extend({ 
 
    value: 42, 
 
    demoMethod: function() { 
 
    return this.value; 
 
    } 
 
}); 
 

 
DemoClass.include({ 
 
    baseDemoMethod: DemoClass.prototype.demoMethod, 
 
    demoMethod: function() { 
 
    return this.baseDemoMethod() * 2; 
 
    }, 
 
    secondMethod: function() { 
 
    return this.value; 
 
    } 
 
}); 
 

 
var instance = new DemoClass(); 
 
console.log("value=" + instance.value); 
 
console.log("secondMethod()=" + instance.secondMethod()); 
 
console.log("demoMethod()=" + instance.demoMethod());
<script src="https://unpkg.com/[email protected]/dist/leaflet.js"></script>

1
demoMethod: function() { 
    return DemoClass.prototype.demoMethod.call(this) * 2; 
    }, 

Вы делаете бесконечный рекурсивный вызов, прямо там.

JS иногда странный, и на этот раз это один из тех. Обращаясь к DemoClass.prototype, вы имеете в виду последнее состояние от DemoClass.prototype ... так DemoClass.prototype.demoMethod относится к сам.

Всякий раз, когда вы перезаписываете прототип метода или свойства, предыдущий получает de-referenced and potentially garbage-collected.

Если вы хотите обратиться к предыдущему определению метода, , вы должны сохранить ссылку на предыдущее определение метода.

Это обычно требует некоторого обмана в виде JS closure (сохраняя ссылку на исходное значение в некоторой области контролируемой переменной). Существует множество способов сделать это: сохранить ссылку на предыдущий прототип как свойство класса, например @Jaws; сделать закрытие где-то; сделайте IIFE, как в Leaflet.GridLayer.FadeOut, или что-нибудь, что позволит вам сохранить ссылку на исходное определение метода.