preface
❝
Hello, everyone, my name is TianTian, a love of fidgety, love algorithm Acmer lovers, comb some good JS topics, review or harvest a lot, share to everyone ❤️
❞
The questions are mainly from the fallible questions you’ve seen, as well as the classic “44 JavaScript Puzzlers!” , from the original link
“Stackoverflow” this has a lot of Questions good, can make up a good foundation
❝
JS error prone topic temporarily for a long time not to update, TypeScript is out, TS really smell
➡️ give a small suggestion, can read the first question first, if there is no problem, basically behind also can skip
❞
GitHub repository click here
Let’s start 👇
18 browser interview questions (1.6W words)
.
VS =
Operator precedence
let a = {n : 1};
let b = a;
a.x = a = {n: 2};
console.log(a.x) console.log(b.x) Copy the code
What’s the output?
Have you really figured it out?
The answer
undefined
{ n : 2}
Do you really understand scopes
var a = 0,
b = 0;
function A(a) {
A = function (b) {
console.log(a + b++)
} console.log(a++) } A(1) A(2) Copy the code
I’ll leave you to think, I got it wrong the first time. ‘⌒ `)
“Answer 1 4“
Think about it. You’ll see the light.
The length of the class array
var obj = {
"2" : 3. "3" : 4. "length" : 2. "splice" : Array.prototype.splice,
"push" : Array.prototype.push } obj.push(1) obj.push(2) console.log(obj) Copy the code
The execution result of this code?
[empty × 2, 1, 2, splice: ƒ, push: ƒ]Copy the code
Set obj[2] = 1,obj. Length++ for obj[2] = 1,obj
Set obj[3] = 2,obj. Length++ for obj[3] = 2,obj
When using console.log(), obj has the length attribute and splice method, so it is printed as an array (obj[0] = undefined) (obj[0] = undefined Copy the code
Non-anonymous self-executing function whose name is read-only
var b = 10;
(function b(){
// 'use strict'
b = 20
console.log(b)
}) ()Copy the code
What is the output?
Function b
Copy the code
- Like the title, non-anonymous self-executing function, function name cannot be changed, strict mode will TypeError,- In non-strict mode, no error is reported, and the modification is useless.- If b is not declared, the function is internally scoped. If b is declared, the function is copied- The named Function was foundb(){} so it is used as the value of b-iife functions cannot replicate inside (similar to const)Copy the code
Non-anonymous self-executing function II
var b = 10;
(function b() { // 'use strict'
var b = 20
console.log(window.b)
console.log(b) }) ()Copy the code
What’s the output?
10
20
Var b = 20; var b = 20; The variable b is found in the current scope, so the value of b is set as 20Copy the code
Non-anonymous self-executing function III
var b = 10;
(function b() { console.log(b)
b = 5
console.log(window.b)
var b = 20 console.log(b) }) ()Copy the code
What is the output?
That shouldn’t be a hard question, so I’ll leave you to think about it
Variable ascension
var name = 'World! ';
(function () {
if (typeof name === 'undefined') {
var name = 'Jack';
console.log('Goodbye ' + name);
} else { console.log('Hello ' + name); } }) ();Copy the code
In JavaScript, Fun and var are promoted
The equivalent of
var name = 'World! ';
(function () {
var name;
if (typeof name === 'undefined') {
name = 'Jack';
console.log('Goodbye ' + name); } else { console.log('Hello ' + name); } }) ();Copy the code
To consolidate:
var str = 'World! ';
(function (name) {
if (typeof name === 'undefined') {
var name = 'Jack';
console.log('Goodbye ' + name);
} else { console.log('Hello ' + name); } })(str); Answer: Hello World because name has become a local variable within the functionCopy the code
The largest integer
var END = Math.pow(2, 53);
var START = END - 100;
var count = 0;
for (var i = START; i <= END; i++) {
count++;
} console.log(count); Copy the code
One knowledge point :Infinity
In JS, math.pow (2, 53) == 9007199254740992 is the maximum that can be represented. The maximum plus one is still the maximum. So the loop doesn't stop.Copy the code
Sparse arrays versus private arrays
Var ary = [0];ary[10] = 10;
ary.filter(function(x) { returnx === undefined; });Copy the code
What was the result?
To do this problem, you need to understand sparse arrays and dense arrays
- Sparse arrays and dense arrays in JavaScript
- Array/filter
Have seen the source of the students should know, filter source code, will determine the array index value is not an array of attributes, interested in the students can see I wrote this article about the array: [dry goods 👍] from the detailed operation of JS array to analysis of V8 array.js
0 inary; = >true
3 inary; = >false
10 inary; = >true
So it's uninitialized from three to nine'pit'! These indexes do not exist in the array. These are skipped in the array function call'pit'.Copy the code
So the answer is []
Floating point arithmetic
Var two = 0.2Var one = 0.1Var eight = 0.8Var six = 0.6[two - one == one, eight - six == two]
Copy the code
What do you think the result is? How should you answer this question?
[true.false]
Copy the code
Check out these articles:
- Explore JavaScript accuracy problems and solutions
- Select “Number” from “0.1+0.2=0.30000000000000004”
Switch
function showCase(value) {
switch(value) {
case 'A':
console.log('Case A');
break;
case 'B': console.log('Case B'); break; case undefined: console.log('undefined'); break; default: console.log('Do not know! '); } } showCase(new String('A')); Copy the code
What’s the result?
Switch is a strict comparison. A String instance is not the same as a String.The answer, of course, is'Do not know'
Therefore, in general, write the switch statement, but also recommended to write the default statementCopy the code
String(“A”)
function showCase2(value) {
switch(value) {
case 'A':
console.log('Case A');
break;
case 'B': console.log('Case B'); break; case undefined: console.log('undefined'); break; default: console.log('Do not know! '); } } showCase2(String('A')); Copy the code
What’s the result?
A. Case B. Case C. Case D. CaseAnalytic: String ('A') returns a string
Copy the code
% operator
function isOdd(num) {
return num % 2 == 1;
}
function isEven(num) {
return num % 2 == 0;
} function isSane(num) { return isEven(num) || isOdd(num); } var values = [7, 4, '13', -9, Infinity]; values.map(isSane); Copy the code
What’s the result?
The answer:true.true.true.false.false]
If % is not a value, call Number () to convert it '13'% 2 / / 1Infinity % 2 //NaN Infinity % 2-9%2 // -1Consolidation: 9 % -2 // 1 remainder plus or minus the first operandCopy the code
What is the prototype of an array
Array.isArray( Array.prototype )
Copy the code
The execution result of this code?
The answer:true
1. Array.prototypeArrays are prototyped arrays, objects are prototyped objects, and functions are prototyped functionsCopy the code
Loose equal ==
[] [] = =Copy the code
What’s the answer
The answer:false
Parse: two reference types, ==, compare the address of the referenceCopy the code
= = and! priority
[] = =! []Copy the code
What’s the result?
(1)! The Boolean([]) on the right istruePI, PI is equal to PIfalse
(2) Convert a reference type to a value type by comparing it with a value type. 0 on the left(3) so 0 ==falseThe answer istrue
Copy the code
Add and subtract numbers from strings
'5' + 3
'5' - 3
Copy the code
So what’s the answer?
Answer: 53 2A + b + C + D +Consolidation: typeof (+"1") / /"number"For non-numeric values + - is often used to type the same as Number()Copy the code
A wave of SAO operation + – + + + + – +
1 plus, minus, plus, plus, plus, minus, plus 1Copy the code
So what do I get
Answer: 2例 句 : A +- is an unary addition and subtraction sign. Two minus two is a plus.Consolidation: Another common use of unary operators is to self-execute functionsfunctionFrom a function declaration to an expression.+ - ~! void + function() {} - function() {} ~ function() {} void function() {}Copy the code
Sparse arrays again? Array.prototype.map()
var ary = Array(3);
ary[0]=2
ary.map(function(elem) { return '1'; });
Copy the code
What is the output?
The sparse array
The array in question is actually an array of length 3, but with no content, and operations on the array will skip those uninitialized'pit'.
So the answer is ["1", the empty x 2]Copy the code
Paste the array.prototype. map polyfill here.
Array.prototype.map = function(callback, thisArg) {
var T, A, k;
if (this == null) {
throw new TypeError(' this is null or not defined'); } var O = Object(this); var len = O.length >>> 0; if(typeof callback ! = ='function') { throw new TypeError(callback + ' is not a function'); } if (arguments.length > 1) { T = thisArg; } A = new Array(len); k = 0; while (k < len) { var kValue, mappedValue; if (k in O) { kValue = O[k]; mappedValue = callback.call(T, kValue, k, O); A[k] = mappedValue; } k++; } return A; }; Copy the code
How is JS stored
var a = 111111111111111110000,
b = 1111;
a + b;
Copy the code
The execution result of this code?
Answer: 11111111111111111000In JavaScript, the number type is stored in 64 bits (8 bytes).The 64 bits include 1 sign bit, 11 exponent bits and 52 real bits.2 to the 53 is the maximum.The value is 9007199254740992 (0x20000000000000).Anything beyond that, you're going to get the wrong result.Copy the code
Comparing array sizes
var a = [1, 2, 3],
b = [1, 2, 3],
c = [1, 2, 4]
a == b
a === b
a > c a < c Copy the code
The execution result of this code?
The answer:false.false.false.true
=== === === ===Comparison between reference types is based on lexicographical order, that is, the first item is larger than the first one, and then the second item is the same.Copy the code
Ternary operator precedence
var val = 'smtg';
console.log('Value is ' + (val === 'smtg')?'Something' : 'Nothing');
Copy the code
The execution result of this code?
Answer: SomethingParsing: String concatenation has a higher priority than ternary operationsSo this is the same thing as'Value is true' ? 'Somthing' : 'Nonthing'
Rather than'Value is' + (true ? 'Something' : 'Nonthing')
Consolidation: 1 || fn() && fn() //1 1 | | 1? 2:3; / / 2Copy the code
The prototype
var a = {}, b = Object.prototype;
[a.prototype === b, Object.getPrototypeOf(a) === b]
Copy the code
What is the result of execution
The answer:false.true
The prototype property on the Object instance is aA's __poroto__ points to object. prototype, which is object.getprototypeof (a). The prototype of A is BCopy the code
The prototype II
function f() {}
var a = f.prototype, b = Object.getPrototypeOf(f);
a === b
Copy the code
The execution result of this code?
The answer:false
Constructor f: {constructor: ƒ}B is the prototype object of instance f: ƒ () {[native code]}Copy the code
The name of the function
function foo() {}var oldName = foo.name;
foo.name = "bar";
[oldName, foo.name]
Copy the code
What is the result of code execution?
The answer:"foo"."foo"]
The name of the function is immutable.Copy the code
[typeof null, null instanceof Object]
The answer:"object".false]
Typeof is a pointer to an empty object. It is a BUG in JS designInstanceof actually determines the constructor on the object, null is null and of course there can't be a constructorConsolidation: NULL == undefined //true null === undefined //flase
Copy the code
[[3, 2, 1]. The reduce () Math. The pow, [] the reduce () Math. The pow]
Answer: the ErrorMath.pow (x, y) x to the yReduce (fn, total) fn (total, currentValue, currentIndex, arr)
If a function does not pass an initial value, the first group of the array defaults to the initial value.[3, 2, 1]. The reduce () Math. The powMath.h pow (3, 2) / / 9Math.h pow (9, 1) / / 9 Do you agree or disagree?[].reduce(math.pow) // Empty arrays will give TypeError[1].reduce(math.pow[].reduce(math.pow,1[2].reduce(math.pow,3) // Pass in the initial value, execute the callback function, return 9Copy the code
replace
"1 2 3".replace(/\d/g, parseInt)
Copy the code
What’s the output?
The answer:"1 NaN 3"
Replace () callback takes four arguments:1. Matches2. A string that matches a subexpression in the pattern3, the location of the occurrence4. StringObject itself.If there is no match for the subexpression, the second argument is where it occurs. So the first argument is the match, and the second argument is the position parseInt('1', 0) parseInt('2', 2) // There can be no 2 in base 2 parseInt('3', 4) Copy the code
The eval usage
function f() {}
var parent = Object.getPrototypeOf(f);
f.name // ?
parent.name // ?
typeof eval(f.name) // ?
typeof eval(parent.name) // ? Copy the code
The execution result of this code?
The answer:"f"."Empty"."function", error
The name of f is fParent is f and the name of the prototype object is"" ,
To calculateeval(f.name) is f, and the data type of f isfunction
eval(the parent name) is undefined,"undefined"
Copy the code
new Date()
var a = new Date("2014-03-19"),
b = new Date(2014, 03, 19);
[a.getDay() === b.getDay(), a.getMonth() === b.getMonth()]
Copy the code
The execution result of this code?
The answer:false.false]
Var a = new Date();"2014-03-19") // Can recognize such a string and return the desired date Wed Mar 19 2014 08:00:00 GMT+0800 (CST)
b = new Date(2014, 03, 19); // The parameters should be indexed Sat Apr 19 2014 00:00:00 GMT+0800 (CST)
Month is indexed from 0 and date is indexed from 1GetDay () gets the day of the weekGetMonth () is the month to fetch, so it's different[a.getdate () === B.getdate ()] //true Copy the code
new Date() II
var a = Date(0);
var b = new Date(0);
var c = new Date();
[a === b, b === c, a === c]
Copy the code
The execution result of this code?
The answer:false.false.false]
Parse: When the date is called as a constructor, it returns a relative epoch-making object (JAN 01 1970).When an argument is lost, it returns the current date. When called as a function, it returns a string representation of the current time.A is the string a === b // all different data types, definitelyfalse
B is object B === c // reference type, compared to the reference addressC is also an object. A === c // different data typesfalse Copy the code
new Date() III
var a = new Date("epoch")
Copy the code
What do you think the result is?
答案 : Invalid Date {}Parse: You get "invalid date", which is an actual date object (a date for which the date istrue). But it is invalid. This is because the time inside remains a number, which in this case is NA.In Chrome, undefinedVar d = new milliseconds (year, month, day, hours, minutes, seconds); var d = new milliseconds (year, month, day, hours, minutes, seconds);Copy the code
Function.length
var a = Function.length,
b = new Function().length
a === b
Copy the code
What is the result of this code?
The answer:false
New (); new (); Same thing so I'm going left to rightNew Function() has length 0Consolidation:function fn () {
var a = 1;
} console.log(fn.length) //0 fn is the same as new Function()Copy the code
❝
If look at the past article [sincere full ✍] take you to fill some JS errit-prone pits can give me a like 👍 attention, the following content is the content of this article.
❞
,2,5,10 [1]. The sort ()
If we don’t write callbacks, what sort are we going to do?
By default, JavaScript uses alphanumeric to sort. So it’s [1,10,2,5]
Sort ((a,b) => a-b)
“b” + “a” + +”a” + “a”
What do you think the output is?
The expression above corresponds to ‘b’+’a’+ (+’a’)+’a’, because (+’a’) is NaN, so:
‘b’+’a’+ (+’a’)+’a’ = ‘b’+’a’+ “NaN”+’a’=’baNaNa’
closure
This is a classic JavaScript interview question
let res = new Array(a) for(var i = 0; i < 10; i++){
res.push(function(){
return console.log(i)
})
} res[0] () res[1] () res[2] ()Copy the code
We expect 0,1,2, but we don’t. The reason is “scope”, how to solve?
- [x] uses let instead of var to form block-level scope
- [x] Uses the bind function.
res.push(console.log.bind(null, i))
Copy the code
There are other solutions, such as using IIFE, forming private scopes, and so on.
Another classic closure problem
function fun(n,o) {
console.log(o)
return {
fun:function(m){
return fun(m,n);
} }; } var a = fun(0); a.fun(1); a.fun(2); a.fun(3); //undefined,? ,? ,?var b = fun(0).fun(1).fun(2).fun(3); //undefined,? ,? ,?var c = fun(0).fun(1); c.fun(2); c.fun(3); //undefined,? ,? ,?Copy the code
“I’ll leave you to think about“
Implicit conversion
var a = [0];
if (a) {
console.log(a == true);
} else {
console.log("wut");
} Copy the code
What do you think the answer is? This involves implicit conversions, so I’m going to do a good job of fixing that
// Answer: false
“One more?“
function fn() {
return 20;
}
console.log(fn + 10); // What the output is
Copy the code
function fn() {
return 20;
}
fn.toString = function() {
return 10;
} console.log(fn + 10); // What is the output? Copy the code
function fn() {
return 20;
}
fn.toString = function() {
return 10; } fn.valueOf = function() { return 5; } console.log(fn + 10); // What is the output?Copy the code
“At the end of the day, the JS type conversion is a good fix“
Do you really understand operators
[1 < < 3, 3 2 < < 1, 2]/ / /false.false]
/ / /true.true]
/ / /false.true]
/ / /true.false]
Copy the code
Let’s pick one, the comparison operator, the assignment operator which has higher precedence?
0.1 + 0.2! = = 0.3?
In the interview, ask you this question, if the answer is wrong, estimate the interviewer is very skeptical about the foundation!!
When I ask you this question, you can drag in a lot of questions, like how does JS store decimals? For example, talk about binary, for example, in the actual development, when you encounter precision problems, how do you solve, what do you have a good solution.
Now, after talking about this, you can drag in the maximum safe number, for example, what is the maximum safe integer in JavaScript, and beyond that, how do you solve the precision problem?
What problems does the new BigInt in the ES specification solve, and what bugs do you find in BigInt?
How do you solve the precision problem?
The recommended Number-Precision library is less than 1K in size.
arguments
function sidEffecting(ary) {
ary[0] = ary[2];
}
function bar(a, b, c) {
c = 10
sidEffecting(arguments); return a + b + c; } function demo (arg) { arg.name = 'new Name' } console.log(bar(2.2.2)) Copy the code
When it comes to ES6 grammar, the answer will always be 22, but if you change the question a little bit, it will be a bit worse… .
function sidEffecting(ary) {
ary[0] = ary[2];
}
function bar(a, b, c = 4) {
c = 10
sidEffecting(arguments); return a + b + c; } function demo (arg) { arg.name = 'new Name' } console.log(bar(2, 2, 2)) Copy the code
So what’s the answer? For a more accurate definition of argument on the MDN, see Argument
❝
When a function in non-strict mode “has” remaining arguments, default arguments, and destructed assignments, then the values in the Arguments object “does not” track the values of the arguments (and vice versa).
❞
The bar function has default parameters and is in non-strict mode, so the values of the parameters are not tracked. The natural result is 14
“Please read carefully“
The browser is confused
let demo1 = {class: "Animal".name: 'sheet'};
console.log(demo1.class)
Copy the code
Class is a reserved word (now, class is the keyword). The answer doesn’t matter. The important thing is to avoid reserved words when you choose the attribute name. If used, please quote a[‘class’].
“Keep the word vs keyword“
As far as I’m concerned, keywords have a special meaning and are not used as variable names. Such as
let class = 123;
Copy the code
Now it seems that there must be an error. What should we pay attention to?
let undefined = 123;
Copy the code
This does not cause an error, but it depends on the browser, so undefined is not the keyword. So just to be on the safe side, “it is recommended to use void 0 === undefined when determining whether a variable is undefined.” It is possible that undefined will be assigned as a variable
“Void 0 is undefined“
[“1”, “2”, “3”].map(parseInt)
It’s easy to figure out how to use the map function, how to use the parseInt function
In the case of arrays, I previously wrote an article about “parsing most methods from a source code perspective.”
Go back to: [dry 👍] from the detailed manipulation of JS arrays to a brief analysis of V8 array.js
The map takes two arguments, a callback and a this, which are referred to when the function is called. The callback function takes three arguments, one currentValue, index, and array.
ParseInt takes two arguments: String, Radix
There are two ways to return a NaN
radix
Less than2
Or greater than36
Or,- The first non-space character cannot be converted to a number.
- When radix is 0 or undefined, it is a special case, specific asynchronous MDN
parseInt('1', 0);
parseInt('2', 1);
parseInt('3', 2);
Copy the code
Put the two together and the result is obvious. [1,NaN,NaN]
Why is math.min () bigger than math.max ()?
Math.min() < Math.max() // false
Copy the code
It should be true because the minimum is less than the maximum, but it’s false
The reason:
- Math.min takes zero or more arguments. If multiple arguments are easy to understand, return the smallest of the arguments.
- If there are zero arguments, or no arguments, return “Infinity”.
- Math.max() returns -infinity when no argument is passed.
If the interviewer asks this question, well…
[] concat [1, 2, 3]
What’s the output? [].concat([1,2,3])
/ / [1, 2, 3]
// Uncaught SyntaxError: ....
// undefined
Copy the code
The answer is undefined, and why is that?
-
The first step is to calculate [].concat. The result is array.prototype.concat
-
The second step executes a comma operator that evaluates each of its operands (from left to right) and returns the value of the last operand.
> 1, 2, 3Return to 3Copy the code
-
The third step performs an array access operation or a property access operation
[].concat[1,2,3] is equivalent to array.prototype.concat [3]
So the result is undefined.
[1, 2, NaN, 3]. IndexOf (NaN)
//2 or -1
- The indexOf method performs a strict equality judgment
- NaN ! == NaN
What to do?
let realIsNaN = value= > typeof value === 'number' && isNaN(value);
Copy the code
You need to determine the type first because string conversions first convert to numbers and the conversion fails to NaN. So it’s the same thing as NaN.
isNaN('jjjj') -- - >true
Copy the code
The second way
letrealIsNaN = value => value ! == value;Copy the code
Number.isFinite & isFinite
Number.isFinite('0') === isFinite('0')
Number.isFinite(0) === isFinite('0')
Copy the code
What is the printout? Can you tell me more about it?
❝
Number.isfinite () checks for finite values. Only in contrast to the global isFinite() function, this method does not force a non-numeric argument to be converted to a numeric value. This means that only values of numeric type, finite, will return true.
❞
The natural answer is false,true
An interview question that is easy to dismiss
function Foo() {
getName = function () { alert (1); };
return this;
}
Foo.getName = function() { alert (2); };Foo.prototype.getName = function() { alert (3); };var getName = function() { alert (4); };function getName() { alert (5); } // Please write the following output:Foo.getName(); getName(); Foo().getName(); getName(); new Foo.getName(); new Foo().getName(); new new Foo().getName(); Copy the code
Push method
let newList = [1.2.3].push(4)
console.log(newList.push(4))
Copy the code
What do you think the output is?
// Error
Array.prototype.push() returns the length of the new Array, so 4
Automatic semicolon insertion
function foo1()
{
return {
bar: "hello"
};
} function foo2() { return { bar: "hello" }; } var a=foo1(); var b=foo2(); console.log(a) //Object {bar: "hello"} console.log(b) //underfind // Take a closer look // A 'is added at line 10; ` Copy the code
A semicolon is automatically added at line 10; So it’s going to return undefined
let var
function foo() {
let a = b = 0;
a++;
return a;
}
foo(); typeof a; / / = >??? typeof b; / / = >??? Copy the code
Let a = b = 0; Window. b = 0, let a = b;
Eyesight problem
const length = 4;
const numbers = [];
for(var i = 0; i < length; i++); { numbers.push(i + 1);
}
numbers; / / = >???Copy the code
The only thing to notice is that the for statement is followed by; Sand sculpture topic
Added; In [5] = [5] = [5]
Gets the specified index character in a string
console.log('Hello World'[4])
Copy the code
The square bracket notation is used to get the character at a particular index of the string. Note that earlier versions of IE7 use charAt()
So this output is o
! = =
const name = 'TianTianUp'
console.log(! typeof name ==='string')
console.log(! typeof name ==='object')
Copy the code
Typeof name returns’ string ‘, and ‘string’ is a Truthy value. So! Typeof name returns a Boolean value of false. so
False = = = ‘string’
And false === ‘object’ return false
To detect a value of a type, we should use! == instead of! typeof)
forEach
const nums = [1, 2, 3, 4, 5, 6];
let firstEven;
nums.forEach(n => {
if (n % 2 ===0 ) {
firstEven = n;
return n; } }); console.log(firstEven); Copy the code
The only thing to note is how the forEach source code is written. ForEach cannot terminate a loop with a return, or each callback call terminates the current loop, not the entire loop.
So it’s going to be 6
❤️ Thank you all
If you found this helpful:
-
Like support, let more people can also see this content.
-
Share your thoughts with me in the comments section, and record your thought process in the comments section.
-
If you think it’s good, you can also check out the previous article:
18 browser interview questions (1.6W words)
[dry goods 👍] from the detailed operation of JS array to v8 array.js
[1.2W word 👍] Write to girlfriend’s secret book – how the browser works (on)
[1.1w word] Write to girlfriend’s secret book – how the browser works (render flow) article
[recommend 👍] again to 100 JS output questions sour cool continue (total 1.8w words + consolidate JS foundation)
“Algorithms and Data Structures” linked list of 9 basic operations
This article was typeset using MDNICE