• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    迪恩网络公众号

yeungon/In-JavaScript-we-trust: Embrace JavaScript naturally and confidently wit ...

原作者: [db:作者] 来自: 网络 收藏 邀请

开源软件名称:

yeungon/In-JavaScript-we-trust

开源软件地址:

https://github.com/yeungon/In-JavaScript-we-trust

开源编程语言:

JavaScript 100.0%

开源软件介绍:

In JS we trust - The best way to learn is by building/coding and teaching. I create the challenges to help my friends learn JavaScript and in return it helps me embrace the language in much deeper level. Feel free to clone, fork and pull.


1. What's the output?
function a(x) {
  x++;
  return function () {
    console.log(++x);
  };
}

a(1)();
a(1)();
a(1)();

let x = a(1);
x();
x();
x();
  • A: 1, 2, 3 and 1, 2, 3
  • B: 3, 3, 3 and 3, 4, 5
  • C: 3, 3, 3 and 1, 2, 3
  • D: 1, 2, 3 and 3, 3, 3
Answer

Answer: B

This question revisits closure - one of the most confusing concepts in JavaScript. Closure allows us to create a stateful function and such a function can access to the variable outside of its scope. In a nutshell, a closure can have access to the global variable (scope), father function scope and its own scope.

We have here, the only one correct answer, 3, 3, 3 and 3, 4, 5 because first we simply call the function a(). It works like a normal function and we have not seen anything so-called stateful yet. In the following code, we declare a variable x and it stores the value of function a(1), that is why we get 3. 4. 5 rather than 3, 3, 3.

This kind of gotcha gives me the feeling of static variable in PHP world.


2. What's the output?
function Name(a, b) {
  this.a = a;
  this.b = b;
}

const me = Name("Vuong", "Nguyen");

console.log(!(a.length - window.a.length));
  • A: undefined
  • B: NaN
  • C: true
  • D: false
Answer

Answer: C

We get true in the console. The tricky part is when we create an object from the constructor function Name but we DO NOT USE new keywork. That makes the variable a global one and get the value "Vuong". Remember that it is actually a property of the global object window (in the browser) or global in the nodejs.

We then get a.length ~ 5 and window.a.length ~ 5 which return 0. !0 returns true.

Imagine what would happen when we create the instance me with the new keywork. That is an interesting inquire!


3. What's the output?
const x = function (...x) {
  let k = (typeof x).length;
  let y = () => "freetut".length;
  let z = { y: y };

  return k - z.y();
};

console.log(Boolean(x()));
  • A: true
  • B: 1
  • C: -1
  • D: false
Answer

Answer: A

The spread operator ...x might help us obtain the parameter in the function in the form of array. Yet, in Javascript the typeof array return "object" rather than "array". It is totally odd if you are coming from PHP.

That is said, we now have the length of the string object which returns 6. z.y() simply returns the length of the string 'freetut' (7).

Be aware that the function x() (in the form of function express or anonymous function (if you are coming from PHP) return -1 when being called and when converted to bool with Boolean(-1) return true instead of false. Noted that Boolean(0) return false.


4. What's the output?
(function js(x) {
  const y = (j) => j * x;

  console.log(y(s()));

  function s() {
    return j();
  }

  function j() {
    return x ** x;
  }
})(3);
  • A: undefined
  • B: 18
  • C: 81
  • D: 12
Answer

Answer: C

The function js() can be automatically executed without calling it and known as IIFE (Immediately Invoked Function Expression). Noted the parameter x of the function js is actuallly passed with the value 3.

The value return of the function is y(s())), meaning calling three other functions y(), s() and j() because the function s() returns j().

j() returns 3^3 = 27 so that s() returns 27.

y(s()) means y(27) which returns 27*3 = 81.

Note that we can call declare function BEFORE the function is actually declared but not with expression function.


5. What's the output?
var tip = 100;

(function () {
  console.log("I have $" + husband());

  function wife() {
    return tip * 2;
  }

  function husband() {
    return wife() / 2;
  }

  var tip = 10;
})();
  • A: "I have $10";
  • B: "I have $100";
  • C: "I have $50";
  • D: "I have $NaN";
Answer

Answer: D

We have here an IIFE (Immediately Invoked Function Expression). It means we do not have to call it but it will be excuted automatically when declared. The flow is as: husband() returns wife()/2 and wife() returns tip*2.

We might think that tip = 100 because it is a global variable when declaring with var keyword. However, it is actually undefined because we also have var tip = 10 INSIDE the function. As the variable tip is hoisted with default value undefined, the final result would be D. We know that undefined returns NaN when we try to divide to 2 or multiple with 2.

If we do not re-declare var tip = 10; at the end of the function, we will definately get B.

JS is fun, right?


6. What's the output?
const js = { language: "loosely type", label: "difficult" };

const edu = { ...js, level: "PhD" };

const newbie = edu;

delete edu.language;

console.log(Object.keys(newbie).length);
  • A: 2;
  • B: 3;
  • C: 4;
  • D: 5;
Answer

Answer: A

This challenge revises the ES6's feature regarding spread operator ... Spread operator is quite useful for retrieving parameter in function, to unite or combine object and array in JavaScript. PHP also has this feature.

In the variable edu, we use ...js (spread operator here) to combine both objects into one. It works in the same way with array.

Then we declare another variable named newbie. IMPORTANT note: By declaring the variable like that, both variables point to the SAME POSITION in the memory. We may have known something like $a = &$b in PHP, which let both varibles work in the same way. We might have known about pass by reference in the case.

Then we have 2 as edu.language is deleted. Both objects now have only two elements.

Now is time to think about coping an object in JS either shallow or deep one.


7. What's the output?
var candidate = {
  name: "Vuong",
  age: 30,
};

var job = {
  frontend: "Vuejs or Reactjs",
  backend: "PHP and Laravel",
  city: "Auckland",
};

class Combine {
  static get() {
    return Object.assign(candidate, job);
  }

  static count() {
    return Object.keys(this.get()).length;
  }
}

console.log(Combine.count());
  • A: 5;
  • B: 6;
  • C: 7;
  • D: 8;
Answer

Answer: A

The buit-in method Object.assign(candidate, job) merges the two objects candidate and job into one object. Then the method Object.keys counts the number of key in the object.

Note that two methods get() and count() are defined as static, so they need to be called statically using Class.staticmethod() syntax. Then the final object get 5 elements.


8. What's the output?
var x = 1;

(() => {
  x += 1;
  ++x;
})();
((y) => {
  x += y;
  x = x % y;
})(2);
(() => (x += x))();
(() => (x *= x))();

console.log(x);
  • A: 4;
  • B: 50;
  • C: 2;
  • D: 10;
Answer

Answer: A

Initially x is declared with the value 1. In the first IIFE function, there are two operations. First x becomes 2 and then 3.

In the second IIFE function, x = x + y then the current value is 5. In the second operation, it returns only 1 as it undergoes 5%2.

In the third and fouth IIFE functions, we get 2 x = x + x and then 4 x = x * x. It is more than simple.


9. What's the output?
$var = 10;

$f = function($let) use ($var) {
    return ++$let + $var;
};

$var = 15;
echo $f(10);
var x = 10;

const f = (l) => ++l + x;

x = 15;
console.log(f(10));
  • A: 26 and 26;
  • B: 21 and 21;
  • C: 21 and 26;
  • D: 26 and 21;
Answer

Answer: C

This question illustrates the diffences between PHP and JavaScript when handling closure. In the first snippet, we declare a closure with the keyword use. Closure in PHP is simply an anonymous function and the data is passed to the function using the keyword use. Otherwise, it is called as lambda when we do not use the keyword use. You can check the result of the snippet here https://3v4l.org/PSeMY. PHP closure only accepts the value of the variable BEFORE the closure is defined, no matter where it is called. As such, $var is 10 rather than 15.

On the contrary, JavaScript treats the variable a bit different when it is passed to anonymous function. We do not have to use the keyword use here to pass variable to the closure. The variable x in the second snippet is updated before the closure is called, then we get 26.

Note that in PHP 7.4, we have arrow function and we then do not have to use the keyword use to pass the variable to function. Another way to call a global ariable inside a function in PHP is to use the keyword global or employ the built-in GLOBAL variable $GLOBALS.


10. What's the output?
let x = {};
let y = {};
let z = x;

console.log(x == y);
console.log(x === y);
console.log(x == z);
console.log(x === z);
  • A: true true true true;
  • B: false false false false;
  • C: true true false false;
  • D: false false true true;
Answer

Answer: D

Technically, x and y have the same value. Both are empty objects. However, we do not use the value to compare objects.

z is x are two objects referring to the same memory position. In JavaScript, array and object are passed by reference. x and z therefore return true when being compared.


11. What's the output?
console.log("hello");

setTimeout(() => console.log("world"), 0);

console.log("hi");
  • A: "hello" -> "world" -> "hi"
  • B: "hello" -> "hi" -> "world"
  • C: "hi" -> "world" -> "hello"
  • D: "hi" -> "hello" -> "world"
Answer

Answer: B

Given that the function setTimeout() will be kept in the task queue before jumping back to stack, "hello" and "hi" will be printed first, then A is incorrect. That is also the case of the answers C and D.

No matter how many seconds you set to the setTimeout() function, it will run after synchronous code. So we will get "hello" first as it is put into the call stack first. Though the setTimeout() is then being put into the call stack, it will subsequently offload to web API (or Node API) and then being called when other synchronous codes are cleared. It means we then get "hi" and finally "world".

So B is the correct answer.

Credit: @kaitoubg (voz) for your suggestion regarding the timeout throttled by which I have decided to alter the question slightly. It will ensure that readers will not get confused as the previous code might bring out different results when tested on other browsers or environments. The main point of the question is about the discrepancy between the synchronous code and asynchronous code when using setTimeout..


12. What's the output?
String.prototype.lengthy = () => {
  console.log("hello");
};

let x = { name: "Vuong" };

delete x;

x.name.lengthy();
  • A: "Vuong";
  • B: "hello";
  • C: "undefined"
  • D: "ReferenceError"
Answer

Answer: B

String.prototype.someThing = function () {} is the common way to define a new built-in method for String. We can do the same thing with Array, Object or FunctionName where FunctionName is the function designed by ourself.

That is not challenging to realise that "string".lengthy() always returns hello. Yet, the tricky part lies in the delete object where we might think that this expression will entirely delete the object. That is not the case as delete is used to delete the property of the object only. It does not delete the object. Then we get hello rather than ReferenceError.

Note that if we declare object without let, const or var, we then have a global object. delete objectName then return true. Otherwise, it always returns false.


13. What's the output?
let x = {};

x.__proto__.hi = 10;

Object.prototype.hi = ++x.hi;

console.log(x.hi + Object.keys(x).length);
  • A: 10
  • B: 11
  • C: 12
  • D: NaN
Answer

Answer: C

First we have an empty object x, then we add another property hi for x with x.__proto__.hi. Note this is equivalent to Object.prototype.hi = 10 and we are adding to the father object Object the property hi. It means every single object will inherit this propety. The property hi becomes a shared one. Say now we declare a new object such as let y = {}, y now has a propery hi inherited from the father Object. Put it simply x.__proto__ === Object.prototype returns true.

Then we overwrite the property hi with a new value 11. Last we have 11 + 1 = 12. x has one property and x.hi returns 11.

Updated (July 27th 2021). If you write Object.prototype.hi = 11; instead of Object.prototype.hi = ++x.hi; as written in the code above, then Object.keys(x) will return an empty array as Object.keys(object) only returns the property of the object itself, not the inherited ones. It means the final result will be 11 rather than 12. For some reason, the code ``Object.prototype.hi = ++x.hi;will create a property for the objectx` itself and then `Object.keys(x)` gives us the array `["hi"]`.

Yet, if you run console.log(x.hasOwnProperty("hi")) it still returns false. By the way, when you deliberately add a property for x such as x.test = "testing", then console.log(x.hasOwnProperty("test")) returns true.


14. What's the output?
const array = (a) => {
  let length = a.length;
  delete a[length - 1];
  return a.length;
};

console.log(array([1, 2, 3, 4]));

const object = (obj) => {
  let key = Object.keys(obj);
  let length = key.length;
  delete obj[key[length - 1]];

  return Object.keys(obj).length;
};

console.log(object({ 1: 2, 2: 3, 3: 4, 4: 5 }));

const setPropNull = (obj) => {
  let key = Object.keys(obj);
  let length = key.length;
  obj[key[length - 1]] = null;

  return Object.keys(obj).length;
};

console.log(setPropNull({ 1: 2, 2: 3, 3: 4, 4: 5 }));
  • A: 333
  • B: 444
  • C: 434
  • D: 343
Answer

热门推荐
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap