*These can have objects & primitive values
What conversion will be used?
Ehem, it depends on...
function sayHi(x) {
if (!x)
return console.log('Bye');
console.log('Hi');
}
//What will this print?
sayHi(false);
sayHi(null);
sayHi([]);
sayHi(new Boolean(false));
function sayHi(x) {
if (!x)
return console.log('Bye');
console.log('Hi');
}
//What will this print?
sayHi(false); // #=> 'Bye'
sayHi(null); // #=> 'Bye'
sayHi([]); // #=> 'Hi'
sayHi(new Boolean(false)); // #=> 'Hi'
Everything is converted to true, except...
What about new Boolean(false) ?
Number(ToPrimitive(obj,'number'))
String(ToPrimitive(obj,'string'))
ToPrimitive?? What is that?
return obj.valueOf()*
return obj.toString()*
*Fail if toString or valueOf returns a non primitive
return obj.toString()*
return obj.valueOf()*
*Fail if toString or valueOf returns a non primitive
return ToPrimitive(expr, 'string')
return ToPrimitive(expr, 'number')
*Not exactly...
var a = {
valueOf:function() {
console.log("valueOf a");
return "1";
}
};
var b = {
valueOf:function() {
console.log("valueOf b");
return "2";
}
};
console.log(a + b);
console.log(b + a);
console.log(a - b);
console.log(b - a);
console.log(+a);
var a = {
valueOf:function() {
console.log("valueOf a");
return "1";
}
};
var b = {
valueOf:function() {
console.log("valueOf b");
return "2";
}
};
console.log(a + b); // #=> '12'
console.log(b + a); // #=> '21'
console.log(a - b); // #=> -1
console.log(b - a); // #=> 1
console.log(+a); // #=> 1
-> ToPrimitive(a) + ToPrimitive(b)
-> ToPrimitive(a) < ToPrimitive(b)
var a = {
valueOf: function () {
return "2";
}
};
console.log(1 == '1');
console.log(1 == true);
console.log(0 == '');
console.log(null == null);
console.log(null == undefined);
console.log(null == '');
console.log(null == 0);
console.log(NaN == NaN);
console.log(a == 2);
console.log(a == true);
console.log(a == false);
var a = {
valueOf: function () {
return "2";
}
};
console.log(1 == '1'); // #=> true
console.log(1 == true); // #=> true
console.log(0 == ''); // #=> true
console.log(null == null); // #=> true
console.log(null == undefined); // #=> true
console.log(null == ''); // #=> false
console.log(null == 0); // #=> false
console.log(NaN == NaN); // #=> false
console.log(a == 2); // #=> true
console.log(a == true); // #=> false
console.log(a == false); // #=> false
Number(primA) == Number(primB)
ToPrimitive(ob1)==ToPrimitive(ob2)
var a = {
valueOf: function () {
return "2";
}
};
console.log(1 === '1');
console.log(1 === true);
console.log(0 === '');
console.log(null === null);
console.log(null === undefined);
console.log(null === '');
console.log(null === 0);
console.log(NaN === NaN);
console.log(a === 2);
console.log(a === true);
console.log(a === false);
var a = {
valueOf: function () {
return "2";
}
};
console.log(1 === '1'); // #=> false
console.log(1 === true); // #=> false
console.log(0 === ''); // #=> false
console.log(null === null); // #=> true
console.log(null === undefined); // #=> false
console.log(null === ''); // #=> false
console.log(null === 0); // #=> false
console.log(NaN === NaN); // #=> false !!!!!
console.log(a === 2); // #=> false
console.log(a === true); // #=> false
console.log(a === false); // #=> false
console.log(true && false);
console.log(false || true);
console.log(Boolean(true && "pepe"));
if (true && "pepe")
console.log("true, of course!");
console.log(Boolean(false || "pepe"));
if (false || "pepe")
console.log("true again, of course!");
console.log(!(true && "pepe"));
console.log(!(false || "pepe"));
console.log(true && "pepe");
console.log(false || "pepe");
console.log(true && false); // #=> false
console.log(false || true); // #=> true
console.log(Boolean(true && "pepe")); // #=> 'pepe'
if (true && "pepe")
console.log("true, of course!"); // Executed
console.log(Boolean(false || "pepe")); // #=> 'pepe'
if (false || "pepe")
console.log("true again, of course!"); // Executed
console.log(!(true && "pepe")); // #=> false
console.log(!(false || "pepe")); // #=> false
console.log(true && "pepe"); // #=> 'pepe'
console.log(false || "pepe"); // #=> 'pepe'
They do shortcircuit evaluation
They do not return a boolean
They do NOT RETURN A BOOLEAN...
...but the last evaluated expression
function rubyish(x) {
return a = !x,
b = 22,
console.log("Some 'statement' here"),
a + b;
}
console.log(rubyish(true));
for (var i = 0, j;
i < 10;
j ? j : j = 0,
console.log(j),
i++,
j = i * 2);
var helloWorld = void function() {
return 'Hello world';
};
console.log(helloWorld());
var helloWorld = function (x) {
if (x === undefined) return 'Hello world';
return 'HaHaHa!';
};
console.log(helloWorld()); // 'Hello world'
var undefined = true;
console.log(helloWorld()); // 'HaHaHa'
var helloWorld2 = function (x) {
if (x === void 0) return 'Hello world';
return 'HaHaHa!';
};
console.log(helloWorld2()); // 'Hello world'
var hash = {},
key1 = {},
key2 = [];
hash[1] = "Uno (number)";
hash["juan"] = "John";
hash[key1] = "Key 1 value";
hash[key2] = "Key 2 value";
console.log(hash[1]);
console.log(hash["juan"]);
console.log(hash[key1]);
console.log(hash[key2]);
var hash = {},
key1 = {},
key2 = [];
hash[1] = "Uno (number)";
hash["juan"] = "John";
hash[key1] = "Key 1 value";
hash[key2] = "Key 2 value";
console.log(hash[1]); // #=> 'Uno (number)'
console.log(hash["juan"]); // #=> 'John'
console.log(hash[key1]); // #=> 'Key 1 value'
console.log(hash[key2]); // #=> 'Key 2 value'
var hash = {},
key1 = {},
key3 = { name: "juan" },
key4 = ["juan"];
hash["1"] = "Uno (string)";
hash[key3] = "Mary";
hash[key4] = "Beth";
console.log(hash["1"]);
console.log(hash[1]);
console.log(hash[key3], hash[key1]);
console.log(hash[key4], hash["juan"]);
var hash = {},
key1 = {},
key3 = { name: "juan" },
key4 = ["juan"];
hash["1"] = "Uno (string)";
hash[key3] = "Mary";
hash[key4] = "Beth";
console.log(hash["1"]);// 'Uno (string)'
console.log(hash[1]);// 'Uno (string)'
console.log(hash[key3], hash[key1]);// 'Mary', 'Mary'
console.log(hash[key4], hash["juan"]);// 'Beth', 'Beth'
They do not exist
typeof {} == 'object'
Objects are key/value pairs
Value can be any expression
Only strings are allowed as keys
obj.propName -> obj['propName']
obj[expr] -> obj[String(expr)]
var arr = [];
console.log(arr.length);
arr[0] = "First";
console.log(arr.length, arr[0], arr[1]);
arr[2] = "Third";
console.log(arr.length, arr[1], arr[2]);
arr["name"] = "Cool array";
console.log(arr.length, arr["name"]);
arr["5"] = "Weird property";
console.log(arr.length, arr["5"]);
var key1 = {
toString: function () {
return "0";
}
};
arr[key1] = "First again";
console.log(arr.length, arr[0]);
var arr = [];
console.log(arr.length);//0
arr[0] = "First";
console.log(arr.length,arr[0],arr[1]);//1,'First',undefined
arr[2] = "Third";
console.log(arr.length,arr[1],arr[2]);//3,undefined,'Third'
arr["name"] = "Cool array";
console.log(arr.length, arr["name"]);//3,'Cool array'
arr["5"] = "Weird property";
console.log(arr.length,arr["5"]);//6,'Weird property'
var key1 = {
toString: function () {
return "0";
}
};
arr[key1] = "First again";
console.log(arr.length, arr[0]);//6,'First again'
They do not exist
typeof [] == 'object'
Only strings can be indexes
obj[index] -> obj[String(index)]
var arr = ["First", "Second", "Third"];
console.log(arr.length, arr);
arr.length--;
console.log(arr.length, arr);
arr.length++;
console.log(arr.length, arr);
var arr = ["First", "Second", "Third"];
console.log(arr.length, arr);
// #=> 3, ["First", "Second", "Third"]
arr.length--;
console.log(arr.length, arr);
// #=> 2, ["First", "Second"]
arr.length++;
console.log(arr.length, arr);
// #=> 3, ["First", "Second", undefined]
var arr = ["First", "Second", "Third"],
obj = {
"0": "1st",
"1": "2nd",
"2": "3rd",
"length": 3,
"name": "My name",
"age": 22
}, p;
arr.name = "Cool!";
for (p in arr)
console.log(p);
for (p in obj)
console.log(p);
for (p = 0; p < arr.length; p++)
console.log(arr[p]);
for (p = 0; p < obj.length; p++)
console.log(obj[p]);
var outer = 'Hi there!';
function fn(){
var inner="I'm local";
console.log(inner, outer);
if(true) {
var other="other local";
console.log(other);
}
console.log(other);
}
fn();
var outer = 'Hi there!';
function fn(){
var inner="I'm local";
console.log(inner, outer); // "I'm local", 'Hi there!'
if(true) {
var other="other local";
console.log(other); // 'other local'
}
console.log(other); // 'other local'
}
fn();
var x = 'Hi there !';
function fn(){
console.log( x );
var x = 'New Value';
console.log( x );
}
fn();
var x = 'Hi there !';
function fn(){
console.log( x ); // undefined
var x = 'New Value';
console.log( x ); // 'New value'
}
fn();
var sum = function sum(n) {
if (!n)
return 0;
return n + sum(n - 1);
};
console.log(sum(4));
var sum2 = sum;
sum = function () {
return 0;
};
console.log(sum(4));
console.log(sum2(4));
var sum = function sum(n) {
if (!n)
return 0;
return n + sum(n - 1);
};
console.log(sum(4)); // #=> 10
var sum2 = sum;
sum = function () {
return 0;
};
console.log(sum(4)); // #=> 0
console.log(sum2(4)); // #=> 10
var x = +function(x) {return x;}('11'),
y = 22,
z = void function(z) {y+=z; return z;}(y);
console.log(x);
console.log(y);
console.log(z);
var x = +function(x) {return x;}('11'),
y = 22,
z = void function(z) {y+=z; return z;}(y);
console.log(x); // #=> 11 (number)
console.log(y); // #=> 44 (number)
console.log(z); // #=> undefined
var pkg = function () {
var somePrivateVar="private";
function privateHelper() {}
return {
publicMethod:function() {
},
otherPublicMethod:function() {
}
};
}();
function makeLoggersFor(arr) {
var size = arr.length, r = [];
for (var i = 0; i < size; i++) {
r[i] = function () {
console.log(i, arr[i]);
};
}
return r;
}
var logs = makeLoggersFor([1, 2]);
logs[0]();
logs[1]();
function makeLoggersFor(arr) {
var size = arr.length, r = [];
for (var i = 0; i < size; i++) {
r[i] = function (i, el) {
return function () {
console.log(i, el);
};
}(i, arr[i]);
}
return r;
}
var logs = makeLoggersFor([1, 2]);
logs[0]();
logs[1]();
function makeLoggersFor(arr) {
return arr.map(function (el, i) {
return function () {
console.log(i, el);
};
});
}
var logs = makeLoggersFor([1, 2]);
logs[0]();
logs[1]();
var makeLoggersWithStyleFor = function () {
function makeLogger(el, i) {
return function () {
console.log(i, el);
};
}
return function (arr) {
return arr.map(makeLogger);
};
}();
var logs = makeLoggersWithStyleFor([1, 2]);
logs[0]();
logs[1]();
var thisIsAnObject = {
name: 'pepe',
sayHi: function(msg) {
console.log("Hi, I'm ", this.name, msg);
}
};
var otherObject = {
name: 'john',
sayBye: thisIsAnObject.sayHi
};
thisIsAnObject.sayBye('!!!');
otherObject.sayBye('?');
var thisIsAnObject = {
name: 'pepe',
sayHi: function(msg) {
console.log("Hi, I'm ", this.name, msg);
}
}, otherObject = { name: 'john' };
var speak=thisIsAnObject.sayHi;
speak('nice to meet you');
speak.call(otherObject, 'nice to meet you');
speak.apply(otherObject, ['nice to meet you']);
john =
name: 'John'
salutator: ->
console.log _this
_this = 'not this anymore'
console.log _this
(msg = 'Hi') => console.log msg + ' ' + @name
johnSalutator = john.salutator()
johnSalutator 'Bye, bye'
john =
name: 'John'
salutator: ->
console.log _this //> {...this object..}
_this = 'not this anymore'
console.log _this //> 'not this anymore'
(msg = 'Hi') => console.log msg + ' ' + @name
johnSalutator = john.salutator()
johnSalutator 'Bye, bye' //> 'Bye, bye undefined'
Does the Coffee spec say something about this?
console.log !new Boolean(false) //> false
console.log 1 + !new Boolean(false) - true //> 0
// The result of the following depends on the browser
console.log parseInt 1 + !new Boolean(false) - true + "10"
// Prints either 8 or 10
You cannot understand what's happening...
...unless you know JS
(parseInt, Date, etc.)