前端常犯错误小集(《你不知道的JavaScript》)

前端自测,检验你的JS基础是否扎实

  1. js basic types,js基础类型
  2. this,this指针
  3. property,属性
  4. proto && prototype,原型链

1.js basic types

1.1 What's the output?

a = [1, 2, 3, 4];
delete a[1];
console.log(a.length);

answer:4

a:[1, empty, 3, 4]

解析:delete不改变数组长度,只是被删除的元素变成了 undefined 其他的元素的键值还是不变。

1.2 What's the output?

let list = [1, 2, 3, 4];
let alreadyList = [2, 3];

let cloneList = [...list];

for (let i = 0; i < list.length - 1; i++) {
  let item = list[i];
  if (alreadyList.includes(item)) {
    cloneList.splice(i, 1);
  }
}

console.log("...", cloneList);

answer:[1,3]

解析:

1. delete 2 - cloneList[1], cloneList-->[1,3,4];

2. delete 3 - cloneList[2], cloneList --> [1,3]

1.3  What's the output?

console.log(42.toFixed(3));

answer: 报错Uncaught SyntaxError: Invalid or unexpected token

解析 

Within 42.toFixed(3), the . will be regarded as a part of number, so (42.)toFixed(3)throws error.

(42).toFixed(3).   // 42.000

42.0000.toFixed(3).  // 42.000

1.4 What's the output?
 

console.log(0.1 + 0.2 === 0.3);

answer: false

解析: 

浮点数问题

console.log(0.1 + 0.2);    //  0.30000000000000004

1.5 What's the output?

a = "12" + 9;
console.log(a, typeof a);
b = "12" - 9;
console.log(b, typeof b);

answer: 

'129'  string

3 'number'

解析

字符串+数字 = 字符串

字符串- 数字 = 数字

1.6  What's the output?

JSON.stringify(undefined);

JSON.stringify(function() {});

JSON.stringify([1, undefined, function() {}, 4, new Date()]);

JSON.stringify({ a: 2, b: function() {}, c: Symbol.for("ccc"), d: 1 });

answer:

undefined

undefined

"[1,null,null,4,"2019-08-19T07:19:47.675Z"]"

"{"a":2,"d":1}"

解析:

JSON.stringify will ignore undefinedfunctionsymbol

1.7 What's the output?

a = Array(3);
b = new Array(3);
c = Array.apply(null, { length: 3 });
d = [undefined, undefined, undefined];

console.log(
  a.map(function(v, i) {
    return i;
  })
);
console.log(
  b.map(function(v, i) {
    return i;
  })
);
console.log(
  c.map(function(v, i) {
    return i;
  })
);
console.log(
  d.map(function(v, i) {
    return i;
  })
);

answer: 

 [empty × 3]

[empty × 3]

[0, 1, 2]

[0, 1, 2]

解析:

  • Array(num)is as same as new Array(num), since the browser will auto add newin before of Array(num)
  • new Array(3)create a array, in which every member is emptyunit (undefinedtype).
  • a.map(..)b.map(..)will be failed, as the array is full of emptymapwill not iterate them.

1.8  What's the output?

x = [1, 2, { a: 1 }];
y = x;
z = [...x];
y[0] = 2;
(y[2].b = 2), (z[2].a = 4);
console.log(x, y, z);

answer: 

[2, 2, { a: 4, b: 2 }][(2, 2, { a: 4, b: 2 })][(1, 2, { a: 4, b: 2 })];

解析:

  • z = [...x] is shallow copy,浅拷贝

1.9  What's the output?

a = new Array(3);
b = [undefined, undefined, undefined];

console.log(a.join("-"));
console.log(b.join("-"));

answer: 

chrome

--

--

解析: join works differently with map

2. this

2.1 What's the output?

obj = {
  a: 1,
  getA() {
    console.log("getA: ", this.a);
  }
};
obj.getA();
x = obj.getA;
x();
setTimeout(obj.getA, 100);

answer:

getA: 1

getA: undefined

(a timerId number) getA: undefined

解析: 

  • It's Implicitly Lost
  • Even though getA appears to be a reference to obj.getA, in fact, it's really just another reference to getA itself. Moreover, the call-site is what matters, and the call-site is getA(), which is a plain, un-decorated call and thus the default bindingapplies.
  • default bindingmakes thisthe global(Window) or undefined (depends on if this is strict mode).

2.2 What's the output?

obj = {
  a: 1,
  getA: () => {
    console.log("getA: ", this.a);
  }
};
setTimeout(obj.getA.bind(obj), 100);

answer: getA: undefined

解析:Arrow functions can never have their own this bound. Instead, they always delegate to the lexical scope (Window).

2.3 What's the output?

function foo() {
  let a = 2;
  this.bar();
}

function bar() {
  console.log(this.a);
}

foo();

answer:  undefined;

解析: 

  • Every time you feel yourself trying to mix lexical scope look-ups with this, remind yourself: there is no bridge.

2.4 What's the output?

let boss1 = { name: "boss1" };
let boss2 = { name: "boss2" };
let boss1returnThis = function() {
  return this.name;
}.bind(boss1);
console.log(boss1returnThis.bind(boss2)());
console.log(boss1returnThis.apply(boss2));
console.log(boss1returnThis.call(boss2));

answer:

boss1;

boss1;

boss1;

解析:

  • For binded this, it cannot be reassigned, even with .bind(), .apply() or .call()

2.5 What's the output?

let boss1 = { name: "boss1" };
let boss2 = { name: "boss2" };
// Begin pay attention
let boss1returnThis = (() => {
  return this;
}).bind(boss1);
// End pay attention
console.log(boss1returnThis.bind(boss2)());
console.log(boss1returnThis.apply(boss2));
console.log(boss1returnThis.call(boss2));

answer:

Window;

Window;

Window;

解析: 

  • Arrow functions can never have their own this bound. Instead, they always delegate to the lexical scope (Window).
  • For arrow functions, this can't be reassigned, even with .bind(), .apply() or .call()

2.6 What's the output?

var value = 1;
var foo = {
  value: 2,
  bar: function() {
    return this.value;
  }
};

console.log(foo.bar());
console.log((foo.bar = foo.bar)());
console.log((false || foo.bar)());
console.log((foo.bar, foo.bar)());

answer:

2;

1;

1;

1;

解析: 

  • Last 3 console.log do apply GetValue to the result of evaluating Expression.
  • GetValue(lref) changes this to be global(window).

2.7 What's the output?

// Begin pay attention
let value = 1;
let foo = {
  value: 2,
  bar: function() {
    return this.value;
  }
};
// End pay attention
console.log(foo.bar());
console.log((foo.bar = foo.bar)());
console.log((false || foo.bar)());
console.log((foo.bar, foo.bar)());

answer:

2;

undefined;

undefined;

undefined;

解析: 

  • let is not global while var is. So the following code will output 1 undefined 2

3. property

3.1 What's the output?

x = Symbol("x");
a = [2, 3, 4, 5, 6, 7];
a.b = 1;
a[x] = 0;
for (let key in a) {
  console.log(key);
}

answer:

0; 1; 2; 3; 4; 5; b;

解析: 

  • for ... in loop will iterates all enumerable, non-Symbol properties.

3.2 What's the output?

x = Symbol("x");
a = [2, 3, 4, 5, 6, 7];
a.b = 1;
a[x] = 0;
for (let val of a) {
  console.log(val);
}

answer:

2; 3; 4; 5; 6; 7;

解析: 

  • The for...in statement iterates over the enumerable, non-Symbol properties of an object, in an arbitrary order.
  • The for...of statement iterates over values that the iterable object defines to be iterated over.

3.3 What's the output?

class A {
  x = 1;
  getX() {
    return this.x;
  }
}
a = new A();
b = Object.assign({}, a);
c = { ...a };
console.log(b, c, "getX" in b, "getX" in c);

answer: `{x: 1} {x: 1} false false`;

解析:

Object.assign......in...only iterates enumerable, non-Symbol properties of the given object directly, excluding the properties of x.__proto__getterand setter.

3.4 What's the output?

obj = { a: 1 };
x = Object.create(obj);
Object.defineProperty(x, "b", {
  value: 2,
  enumerable: false
});
x.c = 3;
for (let k in x) {
  console.log("key: " + k);
}
console.log(Object.getOwnPropertyNames(x));
console.log(Object.keys(x));
console.log(Object.assign({}, x));
JSON.stringify(x);
console.log(x.hasOwnProperty("a"), x.hasOwnProperty("c"));
console.log("a" in x, "c" in x);

answer:

key: c;

key: a;

["b", "c"];

["c"] {c: 3}

"{"c":3}"

false true

true true

解析:

  • x = Object.create(obj) creates a new object, using the existing object obj as the prototype of the newly created object x.
  • for...in: excluding non-enumerable, including __proto__
  • Object.getOwnPropertyNameshasOwnProperty: including non-enumerable, excluding __proto__
  • Object.keysObject.assignJSON.stringify: excluding non-enumerable__proto__
  • ... in ...: including non-enumerable__proto__

3.5 What's the output?

a = { x: 2 };
b = Object.create(a);
console.log(b.hasOwnProperty("x"));
b.x++;
console.log(b.hasOwnProperty("x"));

 answer:false; true;

解析: 

  • Object.create creates a new object, using the existing object as the prototype of the newly created object.
  • b.x++will run b.x = b.x + 1, which will add own property xfor b.

注意:转载自 燕行者 https://juejin.im/post/5d57672ef265da03eb13c68a

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值