I can do this:
class Temp {
constructor() {
this.foo = 'foo'
this.bar = 'bar'
}
getObj() {
let boo = 'boo'
return {
boo
}
}
}
console.log(new Temp().getObj())
//prints { boo: 'boo' }
So how can I do this:
class Temp {
constructor() {
this.foo = 'foo'
this.bar = 'bar'
}
getObj() {
return {
this.foo
}
}
}
console.log(new Temp().getObj())
Is there special syntax or is it not supported?
I guess what you actually look for is:
return { ...this };
or if you want to omit some properties:
const { bar, ...take } = this;
return take;
No, this is not yet supported. You will have to go by {foo: this.foo}.
However, there is a stage 1 proposal for shorthand property definition improvements that would allow you to write {this.foo} as an object literal.
If 'foo' is a public property you can do something like this:
class Foo {
constructor() {
this.foo = 'foo';
}
}
const { foo } = (new Foo());
console.log(foo); // 'foo'
https://repl.it/repls/FastForcefulMice
If you want to use destructuring, you'll need to extract the property to a const, and then use shorthand property names:
class Temp {
constructor() {
this.foo = 'foo'
this.bar = 'bar'
}
getObj() {
const { foo } = this;
return {
foo
}
}
}
console.log(new Temp().getObj())
Related
Getting a function name is pretty straightforward:
const func1 = function() {}
const object = {
func2: function() {}
}
console.log(func1.name);
// expected output: "func1"
console.log(object.func2.name);
// expected output: "func2"
How can I get the string name of a getter/setter, though?
class Example {
get hello() {
return 'world';
}
}
const obj = new Example();
Important note:
I don't want to use a hard-coded string:
Object.getOwnPropertyDescriptor(Object.getPrototypeOf(obj), 'hello')
But get the name, e.g.:
console.log(getGetterName(obj.hello))
// expected output: "hello"
That syntax sets the get function of the hello property descriptor so the name of the function will always be get you can check if the hello property has a get function on it's property descriptor with Object.getOwnPropertyDescriptor().
class Example {
get hello() {
return 'world';
}
}
/*
compiles to / runs as
var Example = (function () {
function Example() {
}
Object.defineProperty(Example.prototype, "hello", {
get: function () {
return 'world';
},
enumerable: true,
configurable: true
});
return Example;
}());
*/
const des = Object.getOwnPropertyDescriptor(Example.prototype, 'hello');
console.log(des.get.name); // get (will always be 'get')
// to check if 'hello' is a getter
function isGetter(name) {
const des = Object.getOwnPropertyDescriptor(Example.prototype, name);
return !!des && !!des.get && typeof des.get === 'function';
}
console.log(isGetter('hello')); // true
Sounds like this won't solve your ultimate issue but:
Object.getOwnPropertyDescriptor(Example.prototype, 'hello').get.name
100% answers the question "How to get getter/setter name in JavaScript/TypeScript?" and it will always be "get"
Edit:
Once you call obj.hello the getter is already called an all you have is the primitive result, but you may be able to use metadata on the property value its self.
function stringPropertyName() {
let _internal;
return (target, key) => {
Object.defineProperty(target, key, {
get: () => {
const newString = new String(_internal);
Reflect.defineMetadata('name', key, newString);
return newString;
},
set: value => {
_internal = value;
}
});
};
}
class Example1 {
#stringPropertyName()
hello = 'world';
}
const obj1 = new Example1();
console.log(Reflect.getMetadata('name', obj1.hello)); // hello
class Example2 {
_hello = 'world';
get hello() {
const newString = new String(this._hello);
Reflect.defineMetadata('name', 'hello', newString);
return newString;
}
set hello(value) {
this._hello = value;
}
}
const obj2 = new Example2();
console.log(Reflect.getMetadata('name', obj2.hello)); // hello
<script src="https://cdnjs.cloudflare.com/ajax/libs/core-js/2.6.11/core.min.js"></script>
If I have
var test = {
return {
foo: function() {
return 1
},
sub: {
bar: function() {
var foo = this.foo() // <--- here, does obviously not work
}
}
}
}
What is the recommended and best way to access foo() from within sub.bar() ...?
To clarify, I want to split an angularjs service into sections.
"Real" code:
angular.module('myApp').factory('Service' function() {
return {
foo: function() {
return 1
},
sub: {
bar: function() {
var foo = this.foo() // <--- here, does obviously not work
}
}
}
})
Since you are using an angular factory, you can Use the Revealing Module Pattern:
angular.module('myApp').factory('Service' function() {
function foo() {
return 1
}
var sub = {
bar: function() {
var foo = foo()
}
}
return {
foo: foo,
sub: sub
}
})
This is not ok:
return {
foo: function() {
return 1
}
}
You need to remove that return statement and within the function bar you can access the function foo using the name of the variable test as follow: test.foo()
var test = {
foo: function() {
return 98989;
},
sub: {
bar: function() {
var foo = test.foo();
console.log(foo);
}
}
};
test.sub.bar();
Another way is using the function bind, but it's overkill:
var test = {
foo: function() {
return 98989;
},
sub: {
bar: function() {
var foo = this.foo(); // Using the object 'this'
console.log(foo);
}
}
};
test.sub.bar.bind(test)();
Now, you can declare a variable service and use that variable:
angular.module('myApp').factory('Service'function() {
var service = {
foo: function() {
return 1
},
sub: {
bar: function() {
var foo = service.foo();
^^^^^^^
}
}
};
return service;
});
I've got a Function that I want to be able to call in 2 ways - and it should behave the same.
Is there any ES6 syntax that will allow me to call the function doBar below using both ways with the same result?
Consider a function like this:
const doBar = ({ foo = 'bar' }) => {
console.log(foo) // should log 'baz'
}
I'm using a framework that binds events like so:
<x-component on-some-event="doBar"></x-component>
which will essentially cause an invocation like so:
// where e = { detail: { foo: 'baz' } }
doBar(e)
.. but I'd like to be able to both call my Function explicitly as well, albeit with a proper call signature like so:
doBar({ foo: 'baz' })
You can use a default parameter. If foo is not found, it will use the value of detail.foo.
const doBar = ({ detail = {}, foo = detail.foo }) => {
console.log(foo) // should log 'baz'
}
doBar({ foo: 'baz' })
doBar({
detail: {
foo: 'baz'
}
});
You can't do this properly in the parameter declaration. Just put your destructuring assignment in the function body:
function doBar(e) {
const { foo = "bar", qux } = e.detail || e;
consoel.log(foo, qux);
}
I'd like to be able to both call my function explicitly as well
I would recommend to not do that. A function should have one signature only and not be overloaded to different types of arguments. Just be explicit about when to use what:
function doBar({ foo = "bar", qux }) {
console.log(foo);
}
function withDetail(fn) {
return e => fn(e.detail)
}
<x-component on-some-event="withDetail(doBar)"></x-component>
doBar({ foo: 'baz' })
No. Not unless you consider this to be an adequate alternative:
const thing = {
detail: {
foo: 'baz'
}
};
doBar(thing.detail);
I want to keep this in class methods.
I can use arrow functions, but I want to override some methods in extended class.
Now I have this solution and it works:
class Foo {
bar = "Context preserved.";
constructor() {
this.foo = this.foo.bind(this);
}
foo() {
alert(this.bar);
}
}
class Foo2 extends Foo {
foo() {
alert(this.bar + " Class extended");
}
}
class Bar {
bar = "Context lost.";
}
let foo = new Foo2();
let bar = new Bar();
foo.foo.apply(bar); // Context preserved. Class extended
Is it a good practice to do it such way? If it is, is there some keyword in typescript to do it automatically?
like
class Foo() {
public conserved foo() { }
}
which generates:
var Foo = (function () {
function Foo() {
this.foo = this.foo.bind(this);
}
Foo.prototype.foo = function () { };
return Foo;
}());
It's a valid practice and it's being used.
I'm unaware of a way to tell typescript to do this automatically, but you can search the issues for something like it.
You can have a decorator that does that for you, for example:
function construct(constructor: Function, methods: string[], args: any[]) {
var c: any = function () {
return constructor.apply(this, args);
}
c.prototype = constructor.prototype;
let instance = new c();
methods.forEach(name => {
instance[name] = instance[name].bind(instance);
});
return instance;
}
function BindMethods(constructor: Function) {
const methods = [] as string[];
Object.keys(constructor.prototype).forEach(name => {
if (typeof constructor.prototype[name] === "function") {
methods.push(name);
}
});
return (...args: any[]) => {
return construct(constructor, methods, args);
};
}
#BindMethods
class Foo {
bar = "Context preserved.";
foo() {
console.log(this.bar);
}
}
let foo = new Foo();
setTimeout(foo.foo, 10);
(code in playground)
I tested it with this simple use case and it worked just fine.
Here is a object I build:
var Obj = {
foo: {
foo: function () {
return this.bar;
},
bar: "bar"
},
bar: "BAR"
}
console.log(Obj.foo.foo());
The Obj.foo.foo method can only access the Obj.foo.bar property's value, or the property of its owner Obj.foo. Can it access the Obj.bar's value? How?
Scope scope and scope
Javascript is a fun language. And one of the realy cool things is the binding of this.
this is defined on function call. So depending on how you call a method. this can change. You can even change it on the fly. Given the following objects:
var Obj = {
foo: {
myFunc: function () {
return this.bar;
},
bar: "bar"
},
bar: "BAR"
}
var Obj2 = {
foo: {
bar: "foobar"
},
bar: "FOOBAR"
}
we can have some fun:
Obj.foo.myFunc(); // "bar"
but we could use call the method binding a different scope
Obj.foo.myFunc.call(Obj); // "BAR"
Here Obj is bound to this.
We can even bind completly different objects:
Obj.foo.myFunc.call(Obj2); // "FOOBAR"
Obj.foo.myFunc.call(Obj2.foo); // "foobar"
or call it ouside of it's scope:
var bar = "something completly different";
var func = Obj.foo.myFunc;
func(); // "something completly different"
so much fun :)
You could introduce a function scope holding the needed reference:
var Obj = (function() {
var that = this;
return {
foo: {
foo: function () {
return that.bar;
},
bar: "bar"
},
bar: "BAR"
})();
I think this should work..
No, there is no way to access "parent" reference - there is no such concept in Javascript. The only way to access Obj.bar from Obj.foo is by direct reference.
var Obj = {
foo: {
foo: function () {
return Obj.bar;
},
bar: "bar"
},
bar: "BAR"
}