1. Usetypeof bar === "object"To determine thebarWhat are the potential pitfalls of being an object? How to avoid this trap?

Although typeof bar === “object” is a reliable way to check if a bar is an object, it is surprising that null is also considered an object in JavaScript!

So, to the surprise of most developers, the following code prints true (instead of false) to the console:

var bar = null;
console.log(typeof bar === "object");  // logs true!Copy the code

By knowing this and checking if bar is null, you can easily avoid the problem:

console.log((bar ! == null) && (typeof bar === "object")); // logs falseCopy the code

There are two other things worth noting in order to answer the whole question:

First, the above solution will return false when bar is a function. In most cases, this is the expected behavior, but when you also want to return true for a function, you can modify the solution above to:

console.log((bar ! == null) && ((typeof bar === "object") || (typeof bar === "function")));Copy the code

Second, the above solution will return true when bar is an array (for example, when var bar = [];) From time to time. In most cases, this is the expected behavior, since arrays are real objects, but when you also want to return false for arrays, you can modify the solution above to:

console.log((bar ! == null) && (typeof bar === "object") && (toString.call(bar) ! == "[object Array]"));Copy the code

Or, if you’re using jQuery:

console.log((bar ! == null) && (typeof bar === "object") && (! $.isArray(bar)));Copy the code

2. What does the following code output to the console and why?

(function(){ var a = b = 3; }) (); console.log("a defined? " + (typeof a ! == 'undefined')); console.log("b defined? " + (typeof b ! == 'undefined'));Copy the code

Since both A and B are defined within the closed scope of functions, and both begin with the var keyword, most JavaScript developers expect typeof A and Typeof B to be undefined in the above example.

However, this is not the case. The problem here is that most developers use the statement var a = b = 3; Misinterpreted as shorthand for the following statement:

var b = 3;
var a = b;Copy the code

But in fact, var a = b = 3; Is actually shorthand for the following statement:

b = 3;
var a = b;Copy the code

So (if you don’t use strict mode), the output of this code snippet is:

a defined? false
b defined? trueCopy the code

But how can B be defined outside the scope of the closed function? Yes, since the statement var a = b = 3; B = 3; Var a = b; Short for, b ends up being a global variable (because it is not prefixed with the var keyword) and therefore remains outside the scope or even enclosing function.

Note that in strict mode, the statement var a = b = 3; Runtime errors with ReferenceError: b is not defined are generated to avoid any headfakes/bugs that might otherwise result. (And the best example of why you should use Strict in your code as a matter of course!)

3. What does the following code output to the console and why?

var myObject = {
    foo: "bar",
    func: function() {
        var self = this;
        console.log("outer func:  this.foo = " + this.foo);
        console.log("outer func:  self.foo = " + self.foo);
        (function() {
            console.log("inner func:  this.foo = " + this.foo);
            console.log("inner func:  self.foo = " + self.foo);
        }());
    }
};
myObject.func();Copy the code

The code above prints the following to the console:

outer func:  this.foo = bar
outer func:  self.foo = bar
inner func:  this.foo = undefined
inner func:  self.foo = barCopy the code

In the external function, both this and self refer to myObject, so both can refer to and access Foo correctly.

In the inner function, this no longer refers to myObject. As a result, this.foo is not defined in the inner function; instead, the local variable self remains in scope and accessible. (Prior to ECMA 5, this in an internal function would point to the global window object; Conversely, because as ECMA 5, the function this in the inner function is undefined.

4. What’s the point of encapsulating the entire content of a JavaScript source file into a function block and why?

This is an increasingly common practice, adopted by many popular JavaScript libraries (jQuery, Node.js, etc.). This technique helps avoid potential name conflicts between different JavaScript modules and libraries by creating a closure around the entire contents of a file and, perhaps most importantly, a private namespace.

Another feature of this technique is that it allows an easy-to-reference (presumably shorter) alias to be used for global variables. This is usually used, for example, in jQuery plug-ins. JQuery allows you to disable $references to the jQuery namespace using jquery.noconflict (). After this is done, your code can still take advantage of the closure technique using $, as shown below:

(function($) { /* jQuery plugin code referencing $ */ } )(jQuery);Copy the code

5. Include it at the beginning of the JavaScript source fileuse strictWhat is the significance and benefit?

The short and most important answer to this question is that Use Strict is a way to automatically enforce stricter parsing and error handling when JavaScript code is running. Code errors that are ignored or fail silently generate errors or throw exceptions. In general, this is a good practice.

Some of the key benefits of the strict model include:

  • Makes debugging easier. Code errors that go unnoticed or fail silently can generate errors or throw exceptions, so alerting you to problems in your code early can lead you to their source code faster.
  • Unexpected global variables. Without a strict schema, assigning a value to an undeclared variable automatically creates a global variable with that name. This is one of the most common mistakes in JavaScript. In strict mode, doing so throws an error.
  • eliminatethisMandatory. If there is no strict schema, reference null or undefined values tothisValues are automatically forced to global variables. This can lead to a lot of headaches and hair-pulling bugs. In strict mode, reference null or undefinedthisValue throws an error.
  • Duplicate attribute names or parameter values are not allowed. When an object is detected (for example,var object = {foo: "bar", foo: "baz"};), or is detected in a function (for example,function foo(val1, val2, val1){}Strict mode throws errors when repeating named parameters, so catching bugs in your code that are almost certainly there can save you a lot of tracing time.
  • makeeval()More secure. In strict mode and in non-strict mode,eval()Behave in different ways. Most obviously, in strict mode, variables and declarations are ineval()Functions inside statements are not created in the contain scope (they are created in the contain scope in non-strict mode, which is also a common source of problems).
  • indeleteThrows an error when using an invalid.deleteThe operator (used to remove properties from an object) cannot be used on properties of an object that are not configurable. Non-strict code will silently fail when attempting to remove a non-configurable property, and strict mode will throw an exception in such cases.

6. Consider the following two functions. Do they return the same thing? Why the same or why not?

function foo1()
{
  return {
      bar: "hello"
  };
}
 
function foo2()
{
  return
  {
      bar: "hello"
  };
}Copy the code

Surprisingly, the two functions return different things. To be more precise:

console.log("foo1 returns:");
console.log(foo1());
console.log("foo2 returns:");
console.log(foo2());Copy the code

Will produce:

foo1 returns:
Object {bar: "hello"}
foo2 returns:
undefinedCopy the code

Not only is this surprising, but it’s particularly confusing that foo2() returns undefined without any error thrown.

The reason has to do with the fact that semicolons are optional in JavaScript (although omitting them is usually very bad form). As a result, when a line of code in foo2() contains a return statement (there is no other code on the line), the semicolon is automatically inserted immediately after the return statement.

No errors are thrown because the rest of the code is perfectly valid, even if it doesn’t get called or do anything (equivalent to it being an unused block of code that defines the property bar equivalent to the string “hello”).

This behavior also supports the convention of placing an open bracket at the end of a line of JavaScript code, rather than at the beginning of a new line of code. As you can see here, this is not just a style preference in JavaScript.

7. NaNWhat is? What is its type? How do you reliably test whether a value is equal toNaN ?

The NaN attribute represents a value that is “not a number.” This particular value is caused by the fact that the operation cannot be performed, either because one of the operands is not a number (for example, “ABC” / 4), or because the result of the operation is not a number (for example, the divisor is zero).

While this may seem simple enough, NaN has some surprising features that can cause headaches if you don’t know about them.

First, although NaN means “not a Number”, its type, believe it or not, is Number:

console.log(typeof NaN === "number");  // logs "true"Copy the code

Besides, NaN is compared to everything — even itself! Return false:

console.log(NaN === NaN);  // logs "false"Copy the code

A semi-reliable way to test whether a number equals NaN is to use the built-in function isNaN(), but even using isNaN() is not a perfect solution.

A better solution is to use Value! == value, if the value is NaN, only true is generated. In addition, ES6 provides a new number.isnan () function, which is different and more reliable than the old global isNaN() function.

8. What does the following code output? And explain why.

The console. The log (0.1 + 0.2); Console. log(0.1 + 0.2 == 0.3);Copy the code

A slightly programmatic answer is: “You can’t be sure. It may or may not print “0.3” and “true”. Numbers and floating-point precision are treated the same in JavaScript and, therefore, may not always yield the expected results. “

The example provided above is a typical example of this problem. But, surprisingly, it prints:

0.30000000000000004
falseCopy the code

9. Discuss writing functionsisInteger(x)To determine whether x is an integer.

This may sound like a piece of cake, but in fact, it’s trivial, as ECMAScript 6 introduces a new function called number.isINTEGER () for just that purpose. The previous ECMAScript 6, however, was a bit more complicated because it did not provide a similar number.isINTEGER () method.

The problem is that in the ECMAScript specification, integers exist only conceptually: that is, numeric values are always stored as floating-point values.

With this in mind, the simplest and cleanest pre-Ecmascript6 workaround (which was also very robust in returning false, even if a non-numeric value, such as string or NULL, was passed to the function) was as follows:

function isInteger(x) { return (x^0) === x; }Copy the code

The following solution is also possible, though not as elegant:

function isInteger(x) { return Math.round(x) === x; }Copy the code

Note that math.ceil () and math.floor () are equivalent to math.round () in the above implementation.

Or:

function isInteger(x) { return (typeof x === 'number') && (x % 1 === 0);Copy the code

A fairly common incorrect solution is:

function isInteger(x) { return parseInt(x, 10) === x; }Copy the code

While this method based on the parseInt function works well for many values of x, it doesn’t work well for large values of x. The problem is that parseInt() forces its first argument to the string before parsing the number. Therefore, once the number becomes large enough, its string is expressed as an exponential (for example, 1e+21). Therefore, parseInt() will parse 1e+21, but will stop parsing when the e string is reached, so it will only return 1. Note:

> String(1000000000000000000000)
'1e+21'
 
> parseInt(1000000000000000000000, 10)
1
 
> parseInt(1000000000000000000000, 10) === 1000000000000000000000
falseCopy the code

10. How can the following lines 1-4 be sorted so that they can be printed to the console when the code is executed? Why is that?

(function() { console.log(1); setTimeout(function(){console.log(2)}, 1000); setTimeout(function(){console.log(3)}, 0); console.log(4); }) ();Copy the code

The serial number is as follows:

4 3 2 1Copy the code

Let’s explain the obvious part first:

  • 1 和 4They are placed first because they are made by simple callsconsole.log()Without any delay in output
  • 2The reason why3After, because2Is output after a delay of 1000 ms (i.e., 1 second), and3It is output after 0 ms delay.

good However, since 3 is output after a 0 ms delay, does that mean it is output immediately? If so, should it print before 4, since 4 is printed on the second line?

To answer this question, you need to understand JavaScript’s event and time Settings correctly.

The browser has an event loop that checks the event queue and handles unfinished events. For example, if the time occurs in the background (for example, the script’s onload event) while the browser is busy (for example, processing an onclick), the event is added to the queue. When the onclick handler completes, the queue is checked and then the event is processed (for example, the onload script is executed).

Similarly, setTimeout() puts the execution of the function it references into an event queue if the browser is busy.

When the second argument to setTimeout() is 0, it means “as soon as possible” to execute the specified function. Specifically, the execution of the function is placed at the beginning of the next timer in the event queue. Note, however, that this is not immediate: the function will not be executed until the next timer starts. This is why, in the example above, the call to console.log(4) occurs before the call to console.log(3) (slightly delayed because the call to console.log(3) is called through setTimeout).

11. Write a simple function (less than 80 characters) that returns a Boolean value indicating whether the string is palindromic.

The following function returns true if STR is a palindrome, and false otherwise.

function isPalindrome(str) {
    str = str.replace(/W/g, '').toLowerCase();
    return (str == str.split('').reverse().join(''));
}Copy the code

Such as:

console.log(isPalindrome("level"));                   // logs 'true'
console.log(isPalindrome("levels"));                  // logs 'false'
console.log(isPalindrome("A car, a man, a maraca"));  // logs 'true'Copy the code

12. Write a sum method that will work when called using any of the following syntax.

The console. The log (sum (2, 3)); // Outputs 5 console.log(sum(2)(3)); // Outputs 5Copy the code

There are (at least) two ways to do this:

Method 1

function sum(x) { if (arguments.length == 2) { return arguments[0] + arguments[1]; } else { return function(y) { return x + y; }; }}Copy the code

In JavaScript, functions can provide access to arguments objects, which provide access to the actual arguments passed to the function. This enables us to use the Length attribute to determine the number of arguments passed to the function at run time.

If you pass two arguments, you simply add them together and return.

Otherwise, we assume it is called as sum(2)(3), so we return an anonymous function that combines the arguments passed to sum() with the arguments passed to the anonymous function.

Method 2

function sum(x, y) {
  if (y !== undefined) {
    return x + y;
  } else {
    return function(y) { return x + y; };
  }
}Copy the code

When calling a function, JavaScript does not require the number of arguments to match the number of arguments in the function definition. If the number of arguments passed is greater than the number in the function definition, the extra arguments are simply ignored. On the other hand, if the number of arguments passed is less than the number in the function definition, the missing argument will be given a undefined value when referenced in the function. So, in the example above, simply checking whether the second argument is undefined can determine how the function is called and how it behaves accordingly.

13. Take a look at the following code snippet:

for (var i = 0; i < 5; i++) {
  var btn = document.createElement('button');
  btn.appendChild(document.createTextNode('Button ' + i));
  btn.addEventListener('click', function(){ console.log(i); });
  document.body.appendChild(btn);
}Copy the code

(a) What is output to the console when the user clicks “Button 4”, and why? (b) Provide one or more alternative implementations that work as intended.

(a) No matter what button the user clicks, the number 5 will always be output to the console. This is because by the time the onclick method is called (for any button), the for loop has ended and the variable I has acquired the value of 5. Candidates will be rewarded if they can talk about how implementing context, mutable objects, active objects, and internal “scope” attributes contribute to closure behavior.

(b) The key to making the code work is to capture the I value each time it passes through the for loop by passing it to a newly created function object. Here are three possible ways to do this:

for (var i = 0; i < 5; i++) {
  var btn = document.createElement('button');
  btn.appendChild(document.createTextNode('Button ' + i));
  btn.addEventListener('click', (function(i) {
    return function() { console.log(i); };
  })(i));
  document.body.appendChild(btn);
}Copy the code

Alternatively, you can wrap all calls to btn.addEventListener in a new anonymous function:

for (var i = 0; i < 5; i++) {
  var btn = document.createElement('button');
  btn.appendChild(document.createTextNode('Button ' + i));
  (function (i) {
    btn.addEventListener('click', function() { console.log(i); });
  })(i);
  document.body.appendChild(btn);
}Copy the code

We can also call the array object’s local forEach method instead of the for loop:

['a', 'b', 'c', 'd', 'e'].forEach(function (value, i) {
  var btn = document.createElement('button');
  btn.appendChild(document.createTextNode('Button ' + i));
  btn.addEventListener('click', function() { console.log(i); });
  document.body.appendChild(btn);
});Copy the code

14. What does the following code output to the console and why?

var arr1 = "john".split('');
var arr2 = arr1.reverse();
var arr3 = "jones".split('');
arr2.push(arr3);
console.log("array 1: length=" + arr1.length + " last=" + arr1.slice(-1));
console.log("array 2: length=" + arr2.length + " last=" + arr2.slice(-1));Copy the code

The output is:

"array 1: length=5 last=j,o,n,e,s"
"array 2: length=5 last=j,o,n,e,s"Copy the code

Arr1 and ARR2 are the same after the above code is executed because:

  • To call an array objectreverse()The method doesn’t just return the array in reverse order; it also reverses the order of the array itself (i.e., in this case, thearr1).
  •  reverse()Method returns a reference to the array itself (in this case,arr1). And as a result,arr2Just one toarr1“(rather than a copy). Therefore, when thearr2Do anything (i.e., when we callarr2.push(arr3);),arr1It will also be affected becausearr1 和 arr2It refers to the same object.

Here are a few side points that can sometimes cause you to flip in the gutter when answering this question:

The push() method of passing an array to another array maps the entire array as a single element to the end of the array. The result is the statement arr2.push(arR3); Add ARR3 to the whole as a single element to the end of ARR2 (that is, it does not concatenate two arrays, which is the purpose of the concat() method).

Like Python, JavaScript advertises negative subscripts in array method calls, such as slice() as a method that references the last element of an array: -1, for example, denotes the last element in the array, and so on.

15. What does the following code output to the console and why?

console.log(1 +  "2" + "2");
console.log(1 +  +"2" + "2");
console.log(1 +  -"1" + "2");
console.log(+"1" +  "1" + "2");
console.log( "A" - "B" + "2");
console.log( "A" - "B" + 2);Copy the code

The code above prints the following to the console:

"122"
"32"
"02"
"112"
"NaN2"
NaNCopy the code

The reason is that…

The fundamental problem here is that JavaScript (ECMAScript) is a weakly typed language that performs automatic type conversions on values to fit the operation being performed. Let’s use the example above to illustrate how this is done.

Example 1:1 + “2” + “2” Output: “122” Description: 1 + “2” is the first operation performed. Since one of the operands (“2”) is a string, JavaScript assumes that it needs to perform string concatenation, so it converts the type of 1 to “1”, and 1 + “2” results in “12”. And then 12 plus 2 is 122.

Example 2:1 + +”2″ +”2″ Output: “32” Description: Depending on the order of operations, the first operation to be performed is +”2″ (the extra + before the first “2” is treated as a unary operator). Therefore, JavaScript converts the type “2” to a number, and then applies the unary + sign (that is, treats it as a positive number). As a result, the next operation is 1 + 2, which of course is 3. We then need to perform an operation between a number and a string (i.e., 3 and “2”), and again, JavaScript converts the numeric type to a string and performs a concatenation of strings to produce “32”.

Example 3:1 + -“1” + “2” Output: “02” Note: The interpretation is the same as in the previous example, except that the unary operator is – instead of +. First “1” becomes 1, then -1 again when applying -, then adds it to 1 to get 0, converts it to a string, concatenates the last “2” operand to get “02”.

Example 4: +”1″ +”1″ +” 2″ Although the first operand “1” is converted to a numeric value because of the unary + operator type prefixed, it is immediately converted back to a string, when concatenated to the second operand “1”, and then concatenated to the final operand “2”, producing the string “112”.

Example 5: “A” – “B” + “2” Output: “NaN2” Description: Since the operator – cannot be applied to strings, and neither “A” nor “B” can be converted to A value, the result of “A” – “B” is NaN, which is then concatenated with the string “2” to produce “NaN2”.

Example 6: “A” – “B” + 2 Output: NaN Description: See the previous example, “A” – “B” results in NaN. However, applying any operator to NaN and any other numeric operator will still result in NaN.

16. The following recursive code causes a stack overflow if the arraylist is too large. How do you solve this problem while preserving the recursive pattern?

var list = readHugeList(); var nextListItem = function() { var item = list.pop(); if (item) { // process the list item... nextListItem(); }};Copy the code

Potential stack overflows can be avoided by modifying the nextListItem function:

var list = readHugeList(); var nextListItem = function() { var item = list.pop(); if (item) { // process the list item... setTimeout( nextListItem, 0); }};Copy the code

Stack overflows are eliminated because the event loop manipulates the recursion, not the call stack. When nextListItem is run, if item is not empty, the timeout function (nextListItem) is pushed to the event queue and exits, thus empties the call stack. When the event queue runs its timeout event and reaches the next item, the timer is set to call nextListItem again. Therefore, there is no direct recursive call to the method from beginning to end, so the call stack remains empty regardless of the number of iterations.

17. What are “closures” in JavaScript? Give me an example.

A closure is an internal function that accesses variables in the outer (closed) function scope chain. Closures can access variables in three scopes: (1) variables in their scope, (2) variables in the scope of enclosing functions, and (3) global variables.

Here’s a simple example:

var globalVar = "xyz"; (function outerFunc(outerArg) { var outerVar = 'a'; (function innerFunc(innerArg) { var innerVar = 'b'; console.log( "outerArg = " + outerArg + "n" + "innerArg = " + innerArg + "n" + "outerVar = " + outerVar + "n" + "innerVar = " + innerVar + "n" + "globalVar = " + globalVar); }) (456); }) (123);Copy the code

In the example above, variables from innerFunc, outerFunc, and the global namespace are all in innerFunc scope. Therefore, the above code will print the following:

outerArg = 123
innerArg = 456
outerVar = a
innerVar = b
globalVar = xyzCopy the code

18. What does the following code output:

for (var i = 0; i < 5; i++) {
  setTimeout(function() { console.log(i); }, i * 1000 );
}Copy the code

Explain your answer. What does a closure do here?

Instead of displaying the values 0,1,2,3, and 4 as expected, the code above displays 5, 5, 5, 5, and 5.

The reason is that each function executed in the loop will be executed after the entire loop is complete, and therefore, will refer to the last value stored in I, which is 5.

Closures can prevent this problem by creating a unique scope for each iteration, storing each unique value of a variable within the scope, as follows:

for (var i = 0; i < 5; i++) {
	(function(x) {
    	setTimeout(function() { console.log(x); }, x * 1000 );
    })(i);
}Copy the code

This outputs 0,1,2,3, and 4 to the console as expected.

19. What will the following code output to the console?

console.log("0 || 1 = "+(0 || 1));
console.log("1 || 2 = "+(1 || 2));
console.log("0 && 1 = "+(0 && 1));
console.log("1 && 2 = "+(1 && 2));Copy the code

And explain.

This code will print:

1 = 1 1 0 | | | | 2 = 1 0 && 1 = 0 1 & 2 = 2Copy the code

In JavaScript, | | and && are logical operators, used in the calculation, from left to right to return to the first can be entirely sure “logical value”.

Or (| |) operator. In shape, such as X | | Y expressions, firstly calculate X and its interpretive execution for a Boolean value. If the Boolean value is true, then return true (1) and no longer evaluate Y because the “or” condition has been satisfied. If the Boolean value of false, so we still can’t know X | | Y is true or not, until we calculate Y, and also to interpreted it as a Boolean value.

Therefore, 0 | of the | 1 results to true (1), the same calculation 1 | | 2.

The and (&&) operator. In an expression of the form X&&Y, X is first evaluated and interpreted as a Boolean value. If the Boolean value is false, then false (0) is returned and Y is no longer evaluated because the “and” condition has failed. If the Boolean value is true, however, we still don’t know if X&&Y is true or false until we evaluate Y and interpret it as a Boolean value as well.

However, the interesting thing about the && operator is that when an expression evaluates to “true”, the expression itself is returned. This is fine, although it evaluates to “true” in terms of logical expressions, but can also be used to return that value if you wish. This explains why, somewhat oddly, 1 && 2 returns 2 (rather than true or 1 as you might think).

20. What is output when the following code is executed? Please explain.

console.log(false == '0')
console.log(false === '0')Copy the code

The code will print:

true
falseCopy the code

In JavaScript, there are two kinds of equality operators. The three equals operator === works like the traditional equals operator: if the expressions on both sides have the same type and the same value, the result is true. The double equal operator, on the other hand, forces only their values to be compared. So, on balance, it’s better to use === instead of ==. ! ==vs ! The same goes for =.

21. What does the following code output? And explain your answer.

var a={},
    b={key:'b'},
    c={key:'c'};
 
a[b]=123;
a[c]=456;
 
console.log(a[b]);Copy the code

This code will print 456 (instead of 123).

The reason: JavaScript implicitly strings parameter values when setting object properties. In this case, since b and C are both objects, they will both be converted to “[Object object]”. The result is that both a[b] and a[c] are equivalent to a[“[object object]”] and are used interchangeably. Therefore, setting or referencing a[c] is exactly the same as setting or referencing a[b].

22. What will the following code output to the console?

console.log((function f(n){return ((n > 1) ? n * f(n-1) : n)})(10));Copy the code

And explain your answer.

The code will print 10! The value of 10! Or 3628800).

The reason is:

The named function f() calls itself recursively, simply returning 1 when f(1) is called. Here is how it is called:

f(1): returns n, which is 1
f(2): returns 2 * f(1), which is 2
f(3): returns 3 * f(2), which is 6
f(4): returns 4 * f(3), which is 24
f(5): returns 5 * f(4), which is 120
f(6): returns 6 * f(5), which is 720
f(7): returns 7 * f(6), which is 5040
f(8): returns 8 * f(7), which is 40320
f(9): returns 9 * f(8), which is 362880
f(10): returns 10 * f(9), which is 3628800Copy the code

23. Look at the code snippet below. What will the console output and why?

(function(x) {
    return (function(y) {
        console.log(x);
    })(2)
})(1);Copy the code

The console prints 1, even though the value of x is never set inside the function. The reason is:

As we explained in the JavaScript Recruitment guide, a closure is a function, along with all the variables or functions that are in the scope of the closure at the time it is created. In JavaScript, a closure is implemented as an “inner function” : that is, a function defined within the body of another function. An important feature of closures is that the inner function still has access to the variables of the outer function.

Therefore, in this case, since x is not defined inside the function, the defined variable X is searched in the outer function scope and is found to have a value of 1.

24. The following code outputs what to the console and why:

var hero = { _name: 'John Doe', getSecretIdentity: function (){ return this._name; }}; var stoleSecretIdentity = hero.getSecretIdentity; console.log(stoleSecretIdentity()); console.log(hero.getSecretIdentity());Copy the code

What’s wrong with the code and how it should be fixed.

The code will print:

undefined
John DoeCopy the code

The first console.log outputs undefined because we are extracting methods from the Hero object, so we call stoleSecretIdentity() in the global context (that is, the window object) where the _NAME property does not exist.

One way to fix the stoleSecretIdentity() function is as follows:

var stoleSecretIdentity = hero.getSecretIdentity.bind(hero);Copy the code

25. When you create a DOM element on a given page, you access functions that access the element itself and all its children (not just its immediate children). For each element accessed, the function should pass the element to the provided callback function.

The arguments to this function are:

  • DOM elements
  • Callback function (which takes a DOM element as an argument)

Accessing all elements of a tree (DOM) is a classic depth-first search algorithm application. Here is a demonstration solution:

function Traverse(p_element,p_callback) {
   p_callback(p_element);
   var list = p_element.children;
   for (var i = 0; i < list.length; i++) {
       Traverse(list[i],p_callback);  // recursive call
   }
}Copy the code


Classic front-end technology books


comments