20

  1. ["1", "2", "3"].map(parseInt)

答案:[1, NaN, NaN]

21

  1. [typeof null, null instanceof Object]

答案:[“object”, false]

22

  1. function f() {};const a = f.prototype,b = Object.getPrototypeOf(f);console.log(a === b);

答案:false

24

  1. console.log([2,1,0].reduce(Math.pow));
  2. console.log([].reduce(Math.pow));
  3. ==>
  4. [2, 1, 0].reduce((acc, cur) => {
  5. return Math.pow(acc, cur)
  6. })

答案:1 报错

26

  1. const value = 'Value is' + !!Number(['0']) ? 'yideng' : 'undefined';
  2. console.log(value);
  3. // 解答:+的优先级大于?

答案:yideng

28

  1. async function async1() {
  2. console.log('async1 start');
  3. await async2();
  4. console.log('async1 end');
  5. }
  6. async function async2() {
  7. console.log('async2');
  8. }
  9. console.log('script start');
  10. setTimeout(function() {
  11. console.log('setTimeout');
  12. }, 0)
  13. async1();
  14. new Promise(function(resolve) {
  15. console.log('promise1');
  16. resolve();
  17. }).then(function() {
  18. console.log('promise2');
  19. });
  20. console.log('script end');

执行流程分析

  • 1.首先,事件循环从宏任务(macrotask)队列开始,这个时候,宏任务队列中,只有一个script(整体代码)任务;从宏任务队列中取一个任务出来执行。
    • a.首先执行console.log(‘script start’) ,输出 ‘script start’ 。
    • b.遇到setTimeout 把 console.log(‘setTimeout’) 放到macroTask队列中。
    • c.执行async1(), 输出 ‘async1 start’ 和 ‘async2’ ,把 console.log(‘async1 end’) 放到micro 队列中。
    • d.执行到promise , 输出 ‘promise1’ , 把 console.log(‘promise2’) 放到micro 队列中。
    • e.执行 console.log(‘script end’) 。输出 ‘script end’
  • 2.macrotask 执行完会执行microtask ,把 microtask quene 里面的 microtask 全部拿出来一次性执行完,所以会输出 ‘async1 end’ 和 ‘ promise2’
  • 3.开始新一轮事件循环,去除一个macrotask执行,所以会输出 “setTimeout”。

下面代码的输出是什么?

  1. const a = {};
  2. const b = { key: "b" };
  3. const c = { key: "c" };
  4. a[b] = 123;
  5. a[c] = 456;
  6. console.log(a[b]); // 456

解析:
对象键自动转换为字符串。我们试图将一个对象设置为对象a的键,其值为123
但是,当对象自动转换为字符串化时,它变成了[Object object]。 所以我们在这里说的是a["Object object"] = 123。 然后,我们可以尝试再次做同样的事情。 c对象同样会发生隐式类型转换。那么,a["Object object"] = 456
然后,我们打印a[b],它实际上是a["Object object"]。 我们将其设置为456,因此返回456

下面代码的输出是什么?

  1. (() => {
  2. let x, y;
  3. try {
  4. throw new Error();
  5. } catch (x) {
  6. (x = 1), (y = 2);
  7. console.log(x);
  8. }
  9. console.log(x);
  10. console.log(y);
  11. })();
  12. // 1 undefined 2

解析:
catch块接收参数x。当我们传递参数时,这与变量的x不同。这个变量x是属于catch作用域的。
之后,我们将这个块级作用域的变量设置为1,并设置变量y的值。 现在,我们打印块级作用域的变量x,它等于1
catch块之外,x仍然是undefined,而y2。 当我们想在catch块之外的console.log(x)时,它返回undefined,而y返回2

闭包

  1. var name = "a";
  2. var object = {
  3. name : "b",
  4. getNameFunc : function(){
  5. return function(){
  6. return this.name;
  7. };
  8. }
  9. };
  10. alert(object.getNameFunc()()); // a
  11. var name = "c";
  12. var object = {
  13. name : "d",
  14. getNameFunc : function(){
  15. var that = this;
  16. return function(){
  17. return that.name;
  18. };
  19. }
  20. };
  21. alert(object.getNameFunc()()); // d

num值?

  1. const num = parseInt("7*6",10);
  2. // 7

只返回字符串的第一个字母,检查字符串中合法的字符,一旦遇到一个在设置进制下不合法的字符,停止解析并忽略后面所有的字符

下面代码的输出是什么?

返回属性的时候,属性的值等于 返回的值,而不是构造函数中设定的值。

  1. function Car() {
  2. this.make = "a";
  3. return {
  4. make: "b"
  5. }
  6. }
  7. const myCar = new Car();
  8. console.log(myCar.make);
  9. // b

作用域

  1. var a = 1;
  2. (function a () {
  3. a = 2;
  4. console.log(a);
  5. })();

解释:立即执行函数,有自己独立的作用域,如果函数名称和内部变量名称冲突,就会永远执行函数本身

new一个函数,如果返回值是这个函数本身

  1. function f(){
  2. return f;
  3. }
  4. console.log(new f() instanceof f); // false
  5. // new f() 返回的是f的函数对象
  1. function f(){}
  2. console.log(new f() instanceof f);
  3. // 答案:true

getPrototypeOf

  1. function f(){}
  2. const a = f.prototype
  3. const b= Object.getPrototypeOf(f)
  4. console.log(a === b)
  5. // false
  6. // a === Object.getPrototypeOf(new f()) true

解析: f.prototype是new创建的f实例的原型 Object.getPrototypeOf(f)是f函数的原型

隐式转换

  1. var a = ?;
  2. if(a == 1 && a== 2 && a== 3){
  3. console.log(1);
  4. }

答案:

  1. // 1.
  2. var a = {
  3. i: 1,
  4. toString: function () {
  5. return a.i++;
  6. }
  7. }
  8. if(a == 1 && a == 2 && a == 3) {
  9. console.log('1');
  10. }
  11. // 2.
  12. var a = [1,2,3];
  13. a.join = a.shift;
  14. console.log(a == 1 && a == 2 && a == 3);
  15. // 3.
  16. var i = 0;
  17. with({
  18. get a() {
  19. return ++i;
  20. }
  21. }) {
  22. if (a == 1 && a == 2 && a == 3)
  23. console.log("1");
  24. }
  25. // 4.
  26. var val = 0;
  27. Object.defineProperty(window, 'a', {
  28. get: function() {
  29. return ++val;
  30. }
  31. });
  32. if (a == 1 && a == 2 && a == 3) {
  33. console.log('1');
  34. }

object作为对象的key

  1. var a1={}, b1='123', c1=123;
  2. a1[b1]='b';
  3. a1[c1]='c';
  4. console.log(a1[b1]);
  5. var a2={}, b2=Symbol('123'), c2=Symbol('123');
  6. a2[b2]='b';
  7. a2[c2]='c';
  8. console.log(a2[b2]);
  9. var a3={}, b3={key:'123'}, c3={key:'456'};
  10. a3[b3]='b';
  11. a3[c3]='c';
  12. console.log(a3[b3]);
  1. // 答案
  2. c b c
  3. // 考察知识点
  4. - 对象的键名只能是字符串和 Symbol 类型。
  5. - 其他类型的键名会被转换成字符串类型。
  6. - 对象转字符串默认会调用 toString 方法。
  7. // 解析
  8. var a1={}, b1='123', c1=123;
  9. a1[b1]='b';
  10. // c1 的键名会被转换成字符串'123',这里会把 b1 覆盖掉。
  11. a1[c1]='c';
  12. // 输出 c
  13. console.log(a1[b1]);
  14. var a2={}, b2=Symbol('123'), c2=Symbol('123');
  15. // b2 是 Symbol 类型,不需要转换。
  16. a2[b2]='b';
  17. // c2 是 Symbol 类型,不需要转换。任何一个 Symbol 类型的值都是不相等的,所以不会覆盖掉 b2。
  18. a2[c2]='c';
  19. // 输出b
  20. console.log(a2[b2]);
  21. var a3={}, b3={key:'123'}, c3={key:'456'};
  22. // b3 不是字符串也不是 Symbol 类型,需要转换成字符串。对象类型会调用 toString 方法转换成字符串 [object Object]
  23. a3[b3]='b';
  24. // c3 不是字符串也不是 Symbol 类型,需要转换成字符串。对象类型会调用 toString 方法转换成字符串 [object Object]。这里会把 b3 覆盖掉。
  25. a3[c3]='c';
  26. // 输出c
  27. console.log(a3[b3]);
  28. // 扩展
  29. 除了前边的Symbol,如果想要不被覆盖 可以使用ES6提供的Map
  30. var a=new Map(), b='123', c=123;
  31. a.set(b,'b');
  32. a.set(c,'c');
  33. a.get(b); // 'b'
  34. a.get(c); // 'c'
  35. /*
  36. Objects 和 Maps 类似的是,它们都允许你按键存取一个值、删除键、检测一个键是否绑定了值。因此(并且也没有其他内建的替代方式了)过去我们一直都把对象当成 Maps 使用。不过 Maps 和 Objects 有一些重要的区别,在下列情况里使用 Map 会是更好的选择:
  37. 1.一个Object的键只能是字符串或者 Symbols,但一个 Map 的键可以是任意值,包括函数、对象、基本类型。
  38. 2.Map 中的键值是有序的,而添加到对象中的键则不是。因此,当对它进行遍历时,Map 对象是按插入的顺序返回键值。
  39. */

原型方法

  1. function Foo() {
  2. Foo.a = function () {
  3. console.log(1);
  4. };
  5. this.a = function () {
  6. console.log(2);
  7. };
  8. }
  9. Foo.prototype.a = function () {
  10. console.log(3);
  11. };
  12. Foo.a = function () {
  13. console.log(4);
  14. };
  15. Foo.a();
  16. let obj = new Foo();
  17. obj.a();
  18. Foo.a();

解析:

  1. Foo.a() 这个是调用 Foo 函数的静态方法 a,虽然 Foo 中有优先级更高的属性方法 a,但 Foo 此时没有被调用,所以此时输出 Foo 的静态方法 a 的结果:4
  2. let obj = new Foo()使用了 new 方法调用了函数,返回了函数实例对象,此时 Foo 函数内部的属性方法初始化,原型方法建立。
  3. obj.a()调用 obj 实例上的方法 a,该实例上目前有两个 a 方法:一个是内部属性方法,另一个是原型方法。当这两者重名时,前者的优先级更高,会覆盖后者,所以输出:2

  4. Foo.a()根据第2步可知 Foo 函数内部的属性方法已初始化,覆盖了同名的静态方法,所以输出:1

引用类型 函数传递

  1. function user(obj) {
  2. obj.name = "a"
  3. obj = new Object()
  4. obj.name = "b"
  5. }
  6. let person = new Object();
  7. user(person);
  8. console.log(person.name);
  9. // a

解析: 对象作为参数,传递进去的是这个对象的地址,obj.name是给person这个对象赋值; obj = new Object()把obj指向另一个对象,obj.name现在是给这个新对象赋值,不影响person这个变量指向的对象;两个obj指向的对象的引用地址不同。

迭代

  1. var obj = { x: 1, y: 2, z: 3 };
  2. [...obj]; // TypeError
  3. // 能否以某种方式为上面的语句使用展开运算而不导致类型错误
  4. // 如果可以,写出解决方式

解析:

  1. var obj = { x: 1, y: 2, z: 3 };
  2. obj[Symbol.iterator] = function(){
  3. // iterator 是一个具有 next 方法的对象,
  4. // 它的返回至少有一个对象
  5. // 两个属性:value&done。
  6. return {
  7. // 返回一个 iterator 对象
  8. next: function () {
  9. if (this._countDown === 3) {
  10. const lastValue = this._countDown;
  11. return { value: this._countDown, done: true };
  12. }
  13. this._countDown = this._countDown + 1;
  14. return { value: this._countDown, done: false };
  15. },
  16. _countDown: 0,
  17. };
  18. };
  19. // 还可以使用 generator 函数来定制对象的迭代行为:
  20. var obj = { x: 1, y: 2, z: 3 };
  21. obj[Symbol.iterator] = function*() {
  22. yield 1;
  23. yield 2;
  24. yield 3;
  25. };

reduce

  1. // 请你完成一个safeGet函数,可以安全的获取无限多层次的数据,一旦数据不存在不会报错,会返回 undefined,例如
  2. var data = { a: { b: { c: 'yideng' } } }
  3. safeGet(data, 'a.b.c') // => yideng
  4. safeGet(data, 'a.b.c.d') // => undefined
  5. safeGet(data, 'a.b.c.d.e.f.g') // => undefined

答案:

  1. // 参考答案
  2. const safeGet = (o, path) => {
  3. try {
  4. return path.split('.').reduce((o, k) => o[k], o)
  5. } catch (e) {
  6. return undefined;
  7. }
  8. }

质数算法

  1. console.time('s')
  2. function isPrime(number) {
  3. if (typeof number !== "number" || !Number.isInteger(number)) return false;
  4. if (number < 2) return false;
  5. if (number === 2) {
  6. return true;
  7. } else if (number % 2 === 0) {
  8. return false;
  9. }
  10. var squareRoot = Math.sqrt(number);
  11. for (var i = 3; i <= squareRoot; i += 2) {
  12. if (number % i === 0) {
  13. return false;
  14. }
  15. }
  16. return true;
  17. };
  18. console.log(isPrime(2711));
  19. console.timeEnd('s')

连等

  1. a=b=5 相当于 a = (b = 5)

首先 b 被赋值为 5,然后 a 也被赋值为 b = 5 的返回值,也就是 5