Merge pull request #2300 from Leaflet/prototypal-options

Make options object prototype-inherited
This commit is contained in:
Vladimir Agafonkin 2013-12-16 15:37:34 -08:00
commit a78dc748ba
4 changed files with 76 additions and 19 deletions

View File

@ -99,12 +99,22 @@ describe("Class", function () {
});
var a = new KlassWithOptions2();
expect(a.options.foo1).to.eql(1);
expect(a.options.foo2).to.eql(3);
expect(a.options.foo3).to.eql(4);
});
expect(a.options).to.eql({
foo1: 1,
foo2: 3,
foo3: 4
});
it("gives new classes a distinct options object", function () {
var K1 = L.Class.extend({options: {}});
var K2 = K1.extend({});
expect(K2.prototype.options).not.to.equal(K1.prototype.options);
});
it("inherits options prototypally", function () {
var K1 = L.Class.extend({options: {}});
var K2 = K1.extend({options: {}});
K1.prototype.options.foo = 'bar';
expect(K2.prototype.options.foo).to.eql('bar');
});
it("adds constructor hooks correctly", function () {

View File

@ -185,7 +185,47 @@ describe('Util', function () {
});
});
// TODO setOptions
describe('#setOptions', function () {
it('sets specified options on object', function () {
var o = {};
L.Util.setOptions(o, {foo: 'bar'});
expect(o.options.foo).to.eql('bar');
});
it('returns options', function () {
var o = {};
var r = L.Util.setOptions(o, {foo: 'bar'});
expect(r).to.equal(o.options);
});
it('accepts undefined', function () {
var o = {};
L.Util.setOptions(o, undefined);
expect(o.options).to.eql({});
});
it('creates a distinct options object', function () {
var opts = {},
o = L.Util.create({options: opts});
L.Util.setOptions(o, {});
expect(o.options).not.to.equal(opts);
});
it("doesn't create a distinct options object if object already has own options", function () {
var opts = {},
o = {options: opts};
L.Util.setOptions(o, {});
expect(o.options).to.equal(opts);
});
it('inherits options prototypally', function () {
var opts = {},
o = L.Util.create({options: opts});
L.Util.setOptions(o, {});
opts.foo = 'bar';
expect(o.options.foo).to.eql('bar');
});
});
describe('#template', function () {
it('evaluates templates with a given data object', function () {

View File

@ -21,11 +21,7 @@ L.Class.extend = function (props) {
}
};
// instantiate class without calling constructor
var F = function () {};
F.prototype = this.prototype;
var proto = new F();
var proto = L.Util.create(this.prototype);
proto.constructor = NewClass;
NewClass.prototype = proto;
@ -50,8 +46,8 @@ L.Class.extend = function (props) {
}
// merge options
if (props.options && proto.options) {
props.options = L.extend({}, proto.options, props.options);
if (proto.options) {
props.options = L.Util.extend(L.Util.create(proto.options), props.options);
}
// mix given properties into the prototype

View File

@ -3,21 +3,27 @@
*/
L.Util = {
extend: function (dest) { // (Object[, Object, ...]) ->
extend: function (dest) {
var sources = Array.prototype.slice.call(arguments, 1),
i, j, len, src;
for (j = 0, len = sources.length; j < len; j++) {
src = sources[j] || {};
src = sources[j];
for (i in src) {
if (src.hasOwnProperty(i)) {
dest[i] = src[i];
}
dest[i] = src[i];
}
}
return dest;
},
create: Object.create || (function () {
function F() {}
return function (proto) {
F.prototype = proto;
return new F();
};
})(),
bind: function (fn, obj) {
var slice = Array.prototype.slice;
@ -107,7 +113,12 @@ L.Util = {
},
setOptions: function (obj, options) {
obj.options = options ? L.extend({}, obj.options, options) : obj.options || {};
if (!obj.hasOwnProperty('options')) {
obj.options = obj.options ? L.Util.create(obj.options) : {};
}
for (var i in options) {
obj.options[i] = options[i];
}
return obj.options;
},