Skip to content

Instantly share code, notes, and snippets.

@ochafik
Last active September 18, 2015 10:44
Show Gist options
  • Save ochafik/1e54b00f14595a230883 to your computer and use it in GitHub Desktop.
Save ochafik/1e54b00f14595a230883 to your computer and use it in GitHub Desktop.
/**
* Gets a property descriptor for a target instance, skipping its class
* and walking up the super-classes hierarchy.
*
* @private
* @param {!Object} target
* @param {!string} name
* @return {!Object.<ObjectPropertyDescriptor>|undefined}
*/
$jscomp.getSuperPropertyDescriptor_ = function(target, name) {
var getPrototypeOf = $jscomp.global.Object.getPrototypeOf;
var getOwnPropertyDescriptor = $jscomp.global.Object.getOwnPropertyDescriptor;
var cls = getPrototypeOf(target);
while (cls != null) {
cls = getPrototypeOf(cls);
var desc = getOwnPropertyDescriptor(cls, name);
if (desc != null) {
return desc;
}
}
return undefined;
};
/**
* Gets a property of a target instance using its super class getter or value,
* or returns undefined if that property is not defined on any ancestor.
*
* @param {!Object} target
* @param {!string} propertyName
* @return {*}
*/
$jscomp.superGet = function(target, propertyName) {
var desc = $jscomp.getSuperPropertyDescriptor_(target, propertyName);
return desc && (desc.get ? desc.get.call(target) : desc.value);
};
/**
* Gets a method of a target instance on its super class, and binds it to the
* target. Note that functions returned by super getters are also treated as
* methods for all practical purposes.
*
* @param {!Object} target
* @param {!string} methodName
* @return {!Function}
*/
$jscomp.superGetBound = function(target, methodName) {
var method = $jscomp.superGet(target, methodName);
if (!(method instanceof Function)) {
throw new Error('Not a function: ' + method);
}
return method.bind(target);
};
/**
* Sets a property on a target instance using its super setter if is defined
* on any ancestor, or setting it as a simple property on the target otherwise.
*
* @param {!Object} target
* @param {!string} propertyName
* @param {*} value
*/
$jscomp.superSet = function(target, propertyName, value) {
var desc = $jscomp.getSuperPropertyDescriptor_(target, propertyName);
if (desc) {
if (!desc.setter) {
throw new TypeError('No setter for super.' + propertyName);
}
desc.setter.call(target, value);
}
target[propertyName] = value;
};
<script src='example.js'></script>
"use strict";
class SuperClass {
get value() { return 1 }
get f() { return function() { return this.value } }
}
class ThisClass extends SuperClass {
test() { return super.f(); }
}
var c = new ThisClass();
console.log(c.test());
console.log(c);
class SuperClass {
set x(v) {}
}
class ThisClass extends SuperClass {
// get x() {}
test() {
// super.foo = 'bar';
// super.bar;
window.console.log(super.x);
// this.x;
// this.x = 1;
// super.x = 1;
}
}
new ThisClass().test();
"use strict";
class Granny {
get x() { return "Granny" }
}
class Mommy extends Granny {
set x(v) { console.log("Mommy.x = " + v) }
}
class Me extends Mommy {
get x() { return "Me" }
test() {
// this.x = "Value for this.x";
super.x = "Value for super.x";
console.log("super.x = " + super.x);
console.log("this.x = " + this.x);
}
}
new Me().test();
"use strict";
class SuperClass {
set x(v) {
this.v = v;
}
}
class ThisClass extends SuperClass {
set x(v) {
super.x = v;
super.y = v;
}
};
var c = new ThisClass();
c.x = 1;
// super.x existed and was called: it set `this.v`.
console.log("c.x = " + c.x); // -> undefined
console.log("c.v = " + c.v); // -> 1
// super.y didn't exist: not an issue, it was set on the instance.
console.log("c.y = " + c.y); // -> 1
"use strict";
class Base {
get x() { return this.value; }
}
class Sub extends Base {
get x() {
console.log("super.x = " + super.x);
console.log("Base.prototype.x = " + Base.prototype.x);
console.log("super.prototype.x = " + super.prototype.x);
}
}
Base.prototype.value = "value of Base.prototype";
var sub = new Sub();
sub.value = "value of the instance";
sub.x;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment