What purpose does the question mark serve in the following code snippet:
Template.lists.selected = function () {
return Session.equals('list_id', this._id) ? 'selected' : '';
};
It's known as a ternary operator in a number of languages. It's a shortcut for a full-on if-then statement.
Instead of writing this:
Template.lists.selected = function () {
if(Session.equals('list_id', this._id)) {
return 'selected';
}
else {
return '';
}
};
You do this:
Template.lists.selected = function () {
return Session.equals('list_id', this._id) ? 'selected' : '';
};
The if return is immediately after the question mark; the else return is after the colon.
Related
Background: Below coding work fine, and i am able to use both function and return the expected value.
Question: Is there any way to simplify below function coding?
red_messages_disabled_p1() {
let s = this.status;
if (s.red_messages[0] === null) {
return 'none';
} else {
return 'inline-block';
}
},
red_messages_disabled_p2() {
let s = this.status;
if (s.red_messages[1] === null) {
return 'none';
} else {
return 'inline-block';
}
},
What did I try?
I tried to figure it out but no idea, guessing it's not possbile to simplify any more, am i correct?
Expecting?
I expecting there maybe simplify way for this coding.
First option :
red_messages_disabled_p(i) {
return this.status.red_messages[i-1] === null ? 'none' : 'inline-block';
}
Second option :
red_messages_disabled_p(i) {
return this.status.red_messages[i-1] ? 'inline-block' : 'none';
}
Get rid of code duplication. Both of your functions contain the same logic. So move that logic into a separate method as shown below:
class MyClass {
status = {red_messages: []}
redMsgDisplayStyle(msg) {
if (msg === null) {
return 'none';
}
return 'inline-block';
}
red_messages_disabled_p1() {
return this.redMsgDisplayStyle(this.status.red_messages[0])
}
red_messages_disabled_p2() {
return this.redMsgDisplayStyle(this.status.red_messages[1])
}
}
This will not only simplify the code, but also make it less error prone in case of you decide to change the logic in the future.
Also, replacing if-else with a ternary operator is probably not a good idea because: 1) it doesn't actually simplify the logic, just a different syntax and 2) ternary operator is less readable.
use a parameterized function
red_messages_disabled(index) {
let s = this.status;
if (s.red_messages[index] === null) {
return 'none';
} else {
return 'inline-block';
}
}
red_messages_disabled_p1() {
return this.red_messages_disabled(0);
};
red_messages_disabled_p2() {
return this.red_messages_disabled(1);
};
Use a ternary operator
red_messages_disabled_p1() {
let s = this.status;
return s.red_messages[0] === null ? 'none' : 'inline-block';
}
red_messages_disabled_p2() {
let s = this.status;
return s.red_messages[1] === null ? 'none' : 'inline-block';
}
There are already lots of good answers for this question, but I wanted to submit my own solution.
const redMessageDisabled => (index) {
return (s.red_messages[index] === null)?"none":"inline-block";
}
However, I think you can just pass s.red_messages[index] to the function
const redMessageDisabled => (data) {
return (data === null) ? "none" : "inline-block";
}
I have this lines of code
let value = productDetails.recentPurchaseDate;
if (!productDetails.salesPrice && !productDetails.recentPurchaseDate) {
value = false;
}
if (!productDetails.presentEstimatedValue) {
value = true;
}
Is it possible to refactor, I need to make it function and this two IF? Thanks in advance
You can do it like this
function getValue({
salesPrice,
recentPurchaseDate,
presentEstimatedValue
}) {
if (!salesPrice && !recentPurchaseDate) return false;
if (!presentEstimatedValue) return true
return recentPurchaseDate
}
and then
let value = getValue(productDetails);
Something like that?
const value = yourNewFn();
function yourNewFn() {
if (!productDetails.salesPrice && !productDetails.recentPurchaseDate) {
value = false;
}
if (!productDetails.presentEstimatedValue) {
value = true;
}
return value;
}
Generally I don't think it is well designed if-conditions, but I don't know your business requirements. Let's try with something like this
let value = productHasRecentPurchaseDate(productDetails); //name should math your business goal
function productHasRecentPurchaseDate(productDetails) {
if (!productDetails.salesPrice && !productDetails.recentPurchaseDate) {
return false;
}
else if (!productDetails.presentEstimatedValue) {
return true;
}
else {
return /*you need all if statement path to return some value, this is last one, please provide what those statements should return if both previous conditions fail*/;
}
}
Then use this
if (!productDetails.salesPrice && !productDetails.recentPurchaseDate && !productDetails.presentEstimatedValue ) : value = false ? value = true;
I'm defining a processor method that returns the lower-case version of the content to achieve this behaviour:
> phrase = new TranslatedPhrase("recognize", "reconocer");
> phrase.palindrome();
true
function reverse(string) {
return Array.from(string).reverse().join("");
}
function Phrase(content) {
this.content = content;
this.processor = function(string) {
return string.toLowerCase();
}
this.processedContent = function processedContent() {
return this.processor(this.content);
}
// Returns true if the phrase is a palindrome, false otherwise.
this.palindrome = function palindrome() {
return this.processedContent() === reverse(this.processedContent());
}
}
function TranslatedPhrase(content, translation) {
this.content = content;
this.translation = translation;
// Returns translation processed for palindrome testing.
this.processedContent = function processedContent() {
return this.processor(this.translation);
}
}
I also tried return this.string.toLowerCase(); but this also doesn't work.
The error I'm currently getting is this:
> let phrase = new TranslatedPhrase("recognize", "reconocer");
undefined
> phrase.palindrome();
Thrown:
TypeError: phrase.palindrome is not a function
Any suggestions as to what I'm missing are greatly appreciated, thx!
I want to achieve this functionality:
I have an object var obj = {};
I have three properties on that obj, obj.zero & obj.one& obj.binaryString
obj.zero & obj.one are methods while obj.binaryString is a string
When I chain the properties, I want them to add their respective digit to the binaryString. So for example:
obj.one.zero.zero.one => makes obj.binaryString = 1001
obj.one.zero.one.one.zero => makes obj.binaryString = 10110
I have achieved the above functionality with this:
function Binary () {
var obj = { binaryString: '' };
Object.defineProperty(obj, 'zero', {
get: function() {
obj.binaryString += '0';
return obj;
}
});
Object.defineProperty(obj, 'one', {
get: function() {
obj.binaryString += '1';
return obj;
}
});
return obj;
}
var binary = new Binary();
binary.one.zero.zero.one // => obj.binaryString becomes '1001'
Now I want to log out the completed binaryString, plus and additionalString which I have accomplished with the code below:
// placed inside Binary constructor function
Object.defineProperty(obj, 'log', {
get: function() {
return function(additionalString) {
console.log(obj.binaryString + additionalString);
};
}
});
So with this current code I can do this:
binary.one.zero.one.zero.one.log(' is the answer');
// logs out `10101 is the answer`
What I want to do is get rid of the log and make the one and zero methods invokable or not so I can achieve this functionality:
binary.one.one.zero.one(' is the result')
// => logs out `1101 is the result`
How can I do this?
I believe it would be similar functionality to how Chalk works:
chalk.blue.bold('Hello world!');
// `blue` is not invoked here but it adds the color blue to the style
chalk.blue('Hello world!');
// `blue` IS invoked here. It adds blue to the style and returns the stylized string
Just Make the obj as function , and print what ever you want .
function Binary () {
var obj = function(msg){ console.log(msg+this.binaryString ) };
obj.binaryString = ''
Object.defineProperty(obj, 'zero', {
get: function() {
obj.binaryString += '0';
return obj;
}
});
Object.defineProperty(obj, 'one', {
get: function() {
obj.binaryString += '1';
return obj;
}
});
return obj;
}
var binary = new Binary();
binary.one.zero.zero.one.zero(" is the result ")
I would like to point out that what you're doing is a very bad/dangerous idea: abusing read properties to mutate the object itself is asking for trouble. You may not see it now, but it's going to lead to pain and heartache down the line in the form of difficult-to-find bugs and convoluted patterns.
What you can do is, which is not so dangerous, is instead of mutating the object itself, return a new instance of Binary with every call to #one or #zero. For example:
function Binary(s) {
this.binaryString = s || ''
}
Object.defineProperty(Binary.prototype, 'zero', {
get: function() {
return new Binary(this.binaryString + '0')
}})
Object.defineProperty(Binary.prototype, 'one', {
get: function() {
return new Binary(this.binaryString + '1')
}})
This is the approach taken by Chalk, and will be much safer and less error-prone.
UPDATE:
After thinking about your problem, and seeing your question, I think the best approach at all is not to use classes at all. You can solve this problem with a pure function-based approach. It's immutable, it's safe, and I believe it's less confusing. Here it is in ES5:
function bin(str) {
if(!str) str = ''
function f(msg) { return str + ' ' + msg }
return Object.defineProperties(f, {
zero: {
get: function() {
return bin(str + '0')
},
},
one: {
get: function() {
return bin(str + '1')
},
},
})
}
And if you can use ES6 (aka ES2015), you can make it much more compact:
function bin(str = '') {
return Object.defineProperties(msg => `${str} ${msg}`, {
zero: { get() { return bin(str + '0') } },
one: { get() { return bin(str + '1') } },
})
}
You would use it like this:
bin().one.zero.one.zero('is the answer') // '1010 is the answer'
I want to test this function:
/js/lib/front.js
var Front = function(){
this.onSignUp = function(){
if (!Form.assertInput("email")) {
$("input[name=email]").focus();
this.showHiddenMessage("Email not set.");
return false;
}
}
}
I have in:
/js/lib/form.js
function Form() {
this.assertInput = function (name, defaultValue) {
var text = $("input[name=" + name + "]").val();
if (defaultValue != null) {
if (defaultValue && text == defaultValue)
return false;
}
if(this.trim(text)) return true;
return false;
}
}
This simple test passing:
test("Front", function() {
var front = new Front()
ok(front);
});
But if I write something like this:
test("On Sign Up ", function() {
var front = new Front()
equal(front.onSignUp(),false,"passing test");
});
I have error:
Died on test #1: Form.assertInput is not a function
I don't understand, what I need test in function like this and how include function inside another function?
I've saved a working fiddle here. As a side note, you might want to check out a tutorial on using qUnit, here.One thing that you need to pay attention to is when you're declaring your functions. It's saying Form.assertInput is not a function because you can't access it like that. You need to use the this keyword, which refers to current context. The code should be something like this:
var Form = function () {
//good to have assertInput first if you're using it in a later function
this.assertInput = function (name, defaultValue) {
var text = $("input[name=" + name + "]").val();
if (defaultValue != null) {
//safer to explicitly close your if statements with {}
if (defaultValue && text == defaultValue) {
return false;
}
}
if ($.trim(text)) { return true; }
return false;
};
this.showHiddenMessage = function (message) {
alert(message);
};
this.onSignUp = function() {
//this will point to the current context, in this case it will be Form class
if (!this.assertInput("email")) {
$("input[name=email]").focus();
this.showHiddenMessage("Email not set.");
return false;
}
};
};
Also in the example code that you gave you're missing the Front class. So I created a dummy one in my fiddle like this:
var Front = function() {};
Here are the tests that were run:
$(document).ready(function() {
test("Front", function() {
var front = new Front();
ok(front);
});
test("On Sign Up ", function() {
var form = new Form();
equal(form.onSignUp(), false, "passing test");
});
});