前端自测,检验你的JS基础是否扎实
- js basic types,js基础类型
- this,this指针
- property,属性
- 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 undefined
, function
, symbol
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 asnew Array(num)
, since the browser will auto addnew
in before ofArray(num)
new Array(3)
create a array, in which every member isempty
unit (undefined
type).a.map(..)
&b.map(..)
will be failed, as the array is full ofempty
,map
will 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 binding
applies. default binding
makesthis
the global(Window
) or undefined (depends on if this isstrict 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 whilevar
is. So the following code will output1 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__
, getter
and 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 objectobj
as the prototype of the newly created objectx
.for...in
: excludingnon-enumerable
, including__proto__
Object.getOwnPropertyNames
&hasOwnProperty
: includingnon-enumerable
, excluding__proto__
Object.keys
&Object.assign
&JSON.stringify
: excludingnon-enumerable
&__proto__
... in ...
: includingnon-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 runb.x = b.x + 1
, which will add own propertyx
forb
.