- 浏览: 1111027 次
文章分类
- 全部博客 (379)
- S2SH (16)
- stuts2 (0)
- java语言 (81)
- JSP (17)
- <html>元素 (11)
- javaweb (4)
- web容器 (3)
- ext (23)
- javaScript (48)
- ant (1)
- liferay (1)
- sql (9)
- css (42)
- 浏览器设置 (3)
- office_world (1)
- eclipse (4)
- 其它 (28)
- 操作系统 (5)
- android (6)
- Struts2 (11)
- RegEx (3)
- mysql (5)
- BigDATA (1)
- Node.js (1)
- Algorithm (10)
- Apache Spark (1)
- 数据库 (5)
- linux (2)
- git (1)
- Adobe (3)
- java语言,WebSocket (1)
- Maven (3)
- SHELL (1)
- XML (2)
- 数学 (2)
- Python (2)
- Java_mysql (1)
- ReactJS (6)
- 养生 (4)
- Docker (1)
- Protocols (3)
- java8 (2)
- 书籍 (1)
- Gradle (2)
- AngularJS (5)
- SpringMVC (2)
- SOAP (1)
- BootstrapCSS (1)
- HTTP协议 (1)
- OAuth2 (1)
最新评论
-
Lixh1986:
Java并发编程:自己动手写一把可重入锁https://blo ...
Java之多线程之Lock与Condition -
Lixh1986:
http://win.51apps.com.cn/https: ...
temp -
ztwsl:
不错,支持很好
HttpServletRequest和ServletRequest的区别 -
guodongkai:
谢谢您能将知识精华汇编总结,让初学者们从原理中学会和提高。
javaScript之function定义 -
kangwen23:
谢谢了,顶顶
struts2中的ValueStack学习
25 Essential JavaScript Interview Questions
1.
使用 typeof bar === "object" 来判断 bar 对象是 object 类型,不足之处?如何避免?
typeof null 返回值也是 object
使用:
另外:
我的解决方案:
2.
下面代码在 console 中输出什么?原因?
Since both a and b are defined within the enclosing scope of the function, and since the line they are on begins with the var keyword, most JavaScript developers would expect typeof a and typeof b to both be undefined in the above example.
However, that is not the case. The issue here is that most developers incorrectly understand the statement var a = b = 3; to be shorthand for:
var b = 3;
var a = b;
But in fact, var a = b = 3; is actually shorthand for:
b = 3;
var a = b;
As a result (if you are not using strict mode), the output of the code snippet would be:
a defined? false
b defined? true
But how can b be defined outside of the scope of the enclosing function? Well, since the statement var a = b = 3; is shorthand for the statements b = 3; and var a = b;, b ends up being a global variable (since it is not preceded by the var keyword) and is therefore still in scope even outside of the enclosing function.
Note that, in strict mode (i.e., with use strict), the statement var a = b = 3; will generate a runtime error of ReferenceError: b is not defined, thereby avoiding any headfakes/bugs that might othewise result. (Yet another prime example of why you should use use strict as a matter of course in your code!)
3.
下面代码在 console 中输出什么?原因?
The above code will output the following to the console:
outer func: this.foo = bar
outer func: self.foo = bar
inner func: this.foo = undefined
inner func: self.foo = bar
In the outer function, both this and self refer to myObject and therefore both can properly reference and access foo.
In the inner function, though, this no longer refers to myObject. As a result, this.foo is undefined in the inner function, whereas the reference to the local variable self remains in scope and is accessible there.
4.
把 JavaScript 文件中的源代码整个包在一个 function 块中的意义及原因?
This is an increasingly common practice, employed by many popular JavaScript libraries (jQuery, Node.js, etc.). This technique creates a closure around the entire contents of the file which, perhaps most importantly, creates a private namespace and thereby helps avoid potential name clashes between different JavaScript modules and libraries.
Another feature of this technique is to allow for an easily referenceable (presumably shorter) alias for a global variable. This is often used, for example, in jQuery plugins. jQuery allows you to disable the $ reference to the jQuery namespace, using jQuery.noConflict(). If this has been done, your code can still use $ employing this closure technique, as follows:
(function($) { /* jQuery plugin code referencing $ */ } )(jQuery);
5.
在 JavaScript 文件的源代码的开头使用 'use strict' 的意义及益处?
the short and most important answer here is that use strict is a way to voluntarily enforce stricter parsing and error handling on your JavaScript code at runtime. Code errors that would otherwise have been ignored or would have failed silently will now generate errors or throw exceptions. In general, it is a good practice.
Some of the key benefits of strict mode include:
Makes debugging easier. Code errors that would otherwise have been ignored or would have failed silently will now generate errors or throw exceptions, alerting you sooner to problems in your code and directing you more quickly to their source.
Prevents accidental globals. Without strict mode, assigning a value to an undeclared variable automatically creates a global variable with that name. This is one of the most common errors in JavaScript. In strict mode, attempting to do so throws an error.
Eliminates this coercion. Without strict mode, a reference to a this value of null or undefined is automatically coerced to the global. This can cause many headfakes and pull-out-your-hair kind of bugs. In strict mode, referencing a a this value of null or undefined throws an error.
Disallows duplicate property names or parameter values. Strict mode throws an error when it detects a duplicate named property in an object (e.g., var object = {foo: "bar", foo: "baz"};) or a duplicate named argument for a function (e.g., function foo(val1, val2, val1){}), thereby catching what is almost certainly a bug in your code that you might otherwise have wasted lots of time tracking down.
Makes eval() safer. There are some differences in the way eval() behaves in strict mode and in non-strict mode. Most significantly, in strict mode, variables and functions declared inside of an eval() statement are not created in the containing scope (they are created in the containing scope in non-strict mode, which can also be a common source of problems).
Throws error on invalid usage of delete. The delete operator (used to remove properties from objects) cannot be used on non-configurable properties of the object. Non-strict code will fail silently when an attempt is made to delete a non-configurable property, whereas strict mode will throw an error in such a case.
-
6.
下面两个函数返回值相同吗?为什么?
Surprisingly, these two functions will not return the same thing. Rather:
console.log("foo1 returns:");
console.log(foo1());
console.log("foo2 returns:");
console.log(foo2());
will yield:
foo1 returns:
Object {bar: "hello"}
foo2 returns:
undefined
Not only is this surprising, but what makes this particularly gnarly is that foo2() returns undefined without any error being thrown.
The reason for this has to do with the fact that semicolons are technically optional in JavaScript (although omitting them is generally really bad form). As a result, when the line containing the return statement (with nothing else on the line) is encountered in foo2(), a semicolon is automatically inserted immediately after the return statement.
No error is thrown since the remainder of the code is perfectly valid, even though it doesn’t ever get invoked or do anything (it is simply an unused code block that defines a property bar which is equal to the string "hello").
This behavior also argues for following the convention of placing an opening curly brace at the end of a line in JavaScript, rather than on the beginning of a new line. As shown here, this becomes more than just a stylistic preference in JavaScript.
结论:
javascript 中,分号是可选的。如果 return 语句的行尾没有分号,则自动加一个。
象上面的代码,运行没有问题。
7.
什么是 NaN? 它是什么类型?如何判断一个值等价于 NaN ?
The NaN property represents a value that is “not a number”. This special value results from an operation that could not be performed either because one of the operands was non-numeric (e.g., "abc" / 4), or because the result of the operation is non-numeric (e.g., an attempt to divide by zero).
While this seems straightforward enough, there are a couple of somewhat surprising characteristics of NaN that can result in hair-pulling bugs if one is not aware of them.
For one thing, although NaN means “not a number”, its type is, believe it or not, Number:
console.log(typeof NaN === "number"); // logs "true"
Additionally, NaN compared to anything – even itself! – is false:
console.log(NaN === NaN); // logs "false"
A semi-reliable way to test whether a number is equal to NaN is with the built-in function isNaN(), but even using isNaN() is an imperfect solution.
A better solution would either be to use value !== value, which would only produce true if the value is equal to NaN. Also, ES6 offers a new Number.isNaN() function, which is a different and more reliable than the old global isNaN() function.
8.What will the code below output? Explain your answer.
An educated answer to this question would simply be: “You can’t be sure. it might print out “0.3” and “true”, or it might not. Numbers in JavaScript are all treated with floating point precision, and as such, may not always yield the expected results.”
The example provided above is classic case that demonstrates this issue. Surprisingly, it will print out:
0.30000000000000004
false
tue
9.
Discuss possible ways to write a function isInteger(x) that determines if x is an integer.
This may sound trivial and, in fact, it is trivial with ECMAscript 6 which introduces a new Number.isInteger() function for precisely this purpose. However, prior to ECMAScript 6, this is a bit more complicated, since no equivalent of the Number.isInteger() method is provided.
The issue is that, in the ECMAScript specification, integers only exist conceptually; i.e., numeric values are always stored as floating point values.
With that in mind, the simplest and cleanest pre-ECMAScript-6 solution (which is also sufficiently robust to return false even if a non-numeric value such as a string or null is passed to the function) would be the following:
function isInteger(x) { return (x^0) === x; }
The following solution would also work, although not as elegant as the one above:
function isInteger(x) { return Math.round(x) === x; }
Note that Math.ceil() or Math.floor() could be used equally well (instead of Math.round()) in the above implementation.
Or alternatively:
function isInteger(x) { return (typeof x === 'number') && (x % 1 === 0); }
One fairly common incorrect solution is the following:
function isInteger(x) { return parseInt(x, 10) === x; }
While this parseInt-based approach will work well for many values of x, once x becomes quite large, it will fail to work properly. The problem is that parseInt() coerces its first parameter to a string before parsing digits. Therefore, once the number becomes sufficiently large, its string representation will be presented in exponential form (e.g., 1e+21). Accordingly, parseInt() will then try to parse 1e+21, but will stop parsing when it reaches the e character and will therefore return a value of 1. Observe:
> String(1000000000000000000000)
'1e+21'
> parseInt(1000000000000000000000, 10)
1
> parseInt(1000000000000000000000, 10) === 1000000000000000000000
false
10.
In what order will the numbers 1-4 be logged to the console when the code below is executed? Why?
The values will be logged in the following order:
1
4
3
2
Let’s first explain the parts of this that are presumably more obvious:
1 and 4 are displayed first since they are logged by simple calls to console.log() without any delay
2 is displayed after 3 because 2 is being logged after a delay of 1000 msecs (i.e., 1 second) whereas 3 is being logged after a delay of 0 msecs.
OK, fine. But if 3 is being logged after a delay of 0 msecs, doesn’t that mean that it is being logged right away? And, if so, shouldn’t it be logged before 4, since 4 is being logged by a later line of code?
The answer has to do with properly understanding JavaScript events and timing.
The browser has an event loop which checks the event queue and processes pending events. For example, if an event happens in the background (e.g., a script onload event) while the browser is busy (e.g., processing an onclick), the event gets appended to the queue. When the onclick handler is complete, the queue is checked and the event is then handled (e.g., the onload script is executed).
Similarly, setTimeout() also puts execution of its referenced function into the event queue if the browser is busy.
When a value of zero is passed as the second argument to setTimeout(), it attempts to execute the specified function “as soon as possible”. Specifically, execution of the function is placed on the event queue to occur on the next timer tick. Note, though, that this is not immediate; the function is not executed until the next tick. That’s why in the above example, the call to console.log(4) occurs before the call to console.log(3) (since the call to console.log(3) is invoked via setTimeout, so it is slightly delayed).
11.
Write a simple function (less than 80 characters) that returns a boolean indicating whether or not a string is a palindrome.
The following one line function will return true if str is a palindrome; otherwise, it returns false.
function isPalindrome(str) {
str = str.replace(/\W/g, '').toLowerCase();
return (str == str.split('').reverse().join(''));
}
For example:
console.log(isPalindrome("level")); // logs 'true'
console.log(isPalindrome("levels")); // logs 'false'
console.log(isPalindrome("A car, a man, a maraca")); // logs 'true'
12.
Write a sum method which will work properly when invoked using either syntax below.
console.log(sum(2,3)); // Outputs 5
console.log(sum(2)(3)); // Outputs 5
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; };
}
}
In JavaScript, functions provide access to an arguments object which provides access to the actual arguments passed to a function. This enables us to use the length property to determine at runtime the number of arguments passed to the function.
If two arguments are passed, we simply add them together and return.
Otherwise, we assume it was called in the form sum(2)(3), so we return an anonymous function that adds together the argument passed to sum() (in this case 2) and the argument passed to the anonymous function (in this case 3).
METHOD 2
function sum(x, y) {
if (y !== undefined) {
return x + y;
} else {
return function(y) { return x + y; };
}
}
When a function is invoked, JavaScript does not require the number of arguments to match the number of arguments in the function definition. If the number of arguments passed exceeds the number of arguments in the function definition, the excess arguments will simply be ignored. On the other hand, if the number of arguments passed is less than the number of arguments in the function definition, the missing arguments will have a value of undefined when referenced within the function. So, in the above example, by simply checking if the 2nd argument is undefined, we can determine which way the function was invoked and proceed accordingly.
13.
Consider the following code snippet:
(a) What gets logged to the console when the user clicks on “Button 4” and why?
(b) Provide one or more alternate implementations that will work as expected.
(a) No matter what button the user clicks the number 5 will always be logged to the console. This is because, at the point that the onclick method is invoked (for any of the buttons), the for loop has already completed and the variable i already has a value of 5. (Bonus points for the interviewee if they know enough to talk about how execution contexts, variable objects, activation objects, and the internal “scope” property contribute to the closure behavior.)
(b) The key to making this work is to capture the value of i at each pass through the for loop by passing it into a newly created function object. Here are three possible ways to accomplish 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);
}
Alternatively, you could wrap the entire call to btn.addEventListener in the 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);
}
Or, we could replace the for loop with a call to the array object’s native forEach method:
['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);
});
14.
What will the code below output to the console and why?
The logged output will be:
"array 1: length=5 last=j,o,n,e,s"
"array 2: length=5 last=j,o,n,e,s"
arr1 and arr2 are the same after the above code is executed for the following reasons:
Calling an array object’s reverse() method doesn’t only return the array in reverse order, it also reverses the order of the array itself (i.e., in this case, arr1).
The reverse() method returns a reference to the array itself (i.e., in this case, arr1). As a result, arr2 is simply a reference to (rather than a copy of) arr1. Therefore, when anything is done to arr2 (i.e., when we invoke arr2.push(arr3);), arr1 will be affected as well since arr1 and arr2 are simply references to the same object.
And a couple of side points here that can sometimes trip someone up in answering this question:
Passing an array to the push() method of another array pushes that entire array as a single element onto the end of the array. As a result, the statement arr2.push(arr3); adds arr3 in its entirety as a single element to the end of arr2 (i.e., it does not concatenate the two arrays, that’s what the concat() method is for).
Like Python, JavaScript honors negative subscripts in calls to array methods like slice() as a way of referencing elements at the end of the array; e.g., a subscript of -1 indicates the last element in the array, and so on.
15.
What will the code below output to the console and why ?
The above code will output the following to the console:
"122"
"32"
"02"
"112"
"NaN2"
NaN
Here’s why…
The fundamental issue here is that JavaScript (ECMAScript) is a loosely typed language and it performs automatic type conversion on values to accommodate the operation being performed. Let’s see how this plays out with each of the above examples.
Example 1: 1 + "2" + "2" Outputs: "122" Explanation: The first operation to be performed in 1 + "2". Since one of the operands ("2") is a string, JavaScript assumes it needs to perform string concatenation and therefore converts the type of 1 to "1", 1 + "2" yields "12". Then, "12" + "2" yields "122".
Example 2: 1 + +"2" + "2" Outputs: "32" Explanation: Based on order of operations, the first operation to be performed is +"2" (the extra + before the first "2" is treated as a unary operator). Thus, JavaScript converts the type of "2" to numeric and then applies the unary + sign to it (i.e., treats it as a positive number). As a result, the next operation is now 1 + 2 which of course yields 3. But then, we have an operation between a number and a string (i.e., 3 and "2"), so once again JavaScript converts the type of the numeric value to a string and performs string concatenation, yielding "32".
Example 3: 1 + -"1" + "2" Outputs: "02" Explanation: The explanation here is identical to the prior example, except the unary operator is - rather than +. So "1" becomes 1, which then becomes -1 when the - is applied, which is then added to 1 yielding 0, which is then converted to a string and concatenated with the final "2" operand, yielding "02".
Example 4: +"1" + "1" + "2" Outputs: "112" Explanation: Although the first "1" operand is typecast to a numeric value based on the unary + operator that precedes it, it is then immediately converted back to a string when it is concatenated with the second "1" operand, which is then concatenated with the final "2" operand, yielding the string "112".
Example 5: "A" - "B" + "2" Outputs: "NaN2" Explanation: Since the - operator can not be applied to strings, and since neither "A" nor "B" can be converted to numeric values, "A" - "B" yields NaN which is then concatenated with the string "2" to yield “NaN2”.
Example 6: "A" - "B" + 2 Outputs: NaN Explanation: As exlained in the previous example, "A" - "B" yields NaN. But any operator applied to NaN with any other numeric operand will still yield NaN.
16.
The following recursive code will cause a stack overflow if the array list is too large. How can you fix this and still retain the recursive pattern?
The potential stack overflow can be avoided by modifying the nextListItem function as follows:
var list = readHugeList();
var nextListItem = function() {
var item = list.pop();
if (item) {
// process the list item...
setTimeout( nextListItem, 0);
}
};
The stack overflow is eliminated because the event loop handles the recursion, not the call stack. When nextListItem runs, if item is not null, the timeout function (nextListItem) is pushed to the event queue and the function exits, thereby leaving the call stack clear. When the event queue runs its timed-out event, the next item is processed and a timer is set to again invoke nextListItem. Accordingly, the method is processed from start to finish without a direct recursive call, so the call stack remains clear, regardless of the number of iterations.
17.
What is a “closure” in JavaScript? Provide an example.
A closure is an inner function that has access to the variables in the outer (enclosing) function’s scope chain. The closure has access to variables in three scopes; specifically: (1) variable in its own scope, (2) variables in the enclosing function’s scope, and (3) global variables.
Here is 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);
In the above example, variables from innerFunc, outerFunc, and the global namespace are all in scope in the innerFunc. The above code will therefore produce the following output:
outerArg = 123
innerArg = 456
outerVar = a
innerVar = b
globalVar = xyz
18.
What will be the output of the following code:
Explain your answer. How could the use of closures help here?
The code sample shown will not display the values 0, 1, 2, 3, and 4 as might be expected; rather, it will display 5, 5, 5, 5, and 5.
The reason for this is that each function executed within the loop will be executed after the entire loop has completed and all will therefore reference the last value stored in i, which was 5.
Closures can be used to prevent this problem by creating a unique scope for each iteration, storing each unique value of the variable within its scope, as follows:
for (var i = 0; i < 5; i++) {
(function(x) {
setTimeout(function() { console.log(x); }, x * 1000 );
})(i);
}
This will produce the presumably desired result of logging 0, 1, 2, 3, and 4 to the console.
19.
What would the following lines of code output to the console?
Explain your answer.
The code will output the following four lines:
0 || 1 = 1
1 || 2 = 1
0 && 1 = 0
1 && 2 = 2
In JavaScript, both || and && are logical operators that return the first fully-determined “logical value” when evaluated from left to right.
The or (||) operator. In an expression of the form X||Y, X is first evaluated and interpreted as a boolean value. If this boolean value is true, then true (1) is returned and Y is not evaluated, since the “or” condition has already been satisfied. If this boolean value is “false”, though, 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.
Accordingly, 0 || 1 evaluates to true (1), as does 1 || 2.
The and (&&) operator. In an expression of the form X&&Y, X is first evaluated and interpreted as a boolean value. If this boolean value is false, then false (0) is returned and Y is not evaluated, since the “and” condition has already failed. If this boolean value is “true”, though, 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 with the && operator is that when an expression is evaluated as “true”, then the expression itself is returned. This is fine, since it counts as “true” in logical expressions, but also can be used to return that value when you care to do so. This explains why, somewhat surprisingly, 1 && 2 returns 2 (whereas you might it expect it to return true or 1).
20.
What will be the output when the following code is executed? Explain.
The code will output:
true
false
In JavaScript, there are two sets of equality operators. The triple-equal operator === behaves like any traditional equality operator would: evaluates to true if the two expressions on either of its sides have the same type and the same value. The double-equal operator, however, tries to coerce the values before comparing them. It is therefore generally good practice to use the === rather than ==. The same holds true for !== vs !=.
21.
What is the output out of the following code? Explain your answer.
The output of this code will be 456 (not 123).
The reason for this is as follows: When setting an object property, JavaScript will implicitly stringify the parameter value. In this case, since b and c are both objects, they will both be converted to "[object Object]". As a result, a[b] anda[c] are both equivalent to a["[object Object]"] and can be used interchangeably. Therefore, setting or referencing a[c] is precisely the same as setting or referencing a[b].
22.
What will the following code output to the console:
The code will output the value of 10 factorial (i.e., 10!, or 3,628,800).
Here’s why:
The named function f() calls itself recursively, until it gets down to calling f(1) which simply returns 1. Here, therefore, is what this does:
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 3628800
23.
Consider the code snippet below. What will the console output be and why?
The output will be 1, even though the value of x is never set in the inner function. Here’s why:
As explained in our JavaScript Hiring Guide, a closure is a function, along with all variables or functions that were in-scope at the time that the closure was created. In JavaScript, a closure is implemented as an “inner function”; i.e., a function defined within the body of another function. An important feature of closures is that an inner function still has access to the outer function’s variables.
Therefore, in this example, since x is not defined in the inner function, the scope of the outer function is searched for a defined variable x, which is found to have a value of 1.
24.
What will the following code output to the console and why:
What is the issue with this code and how can it be fixed.
The code will output:
undefined
John Doe
The first console.log prints undefined because we are extracting the method from the hero object, so stoleSecretIdentity() is being invoked in the global context (i.e., 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);
25.
Create a function that, given a DOM Element on the page, will visit the element itself and all of its descendents (not just its immediate children). For each element visited, the function should pass that element to a provided callback function.
The arguments to the function should be:
a DOM element
a callback function (that takes a DOM element as its argument)
Visiting all elements in a tree (DOM) is a classic Depth-First-Search algorithm application. Here’s an example 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
}
}
-
引自:
https://www.toptal.com/javascript/interview-questions
-
1.
使用 typeof bar === "object" 来判断 bar 对象是 object 类型,不足之处?如何避免?
typeof null 返回值也是 object
使用:
(bar !== null) && (typeof bar === "object")
另外:
/* * 使用 typeof */ typeof function(){ } // "function" typeof Function() // "function" typeof new Function() // "function" typeof undefined // "undefined" typeof null // "object" typeof {} // "object" typeof [] // "object" typeof new function(){} // "object" typeof "abc" // "string" typeof 123 // "number"
/* * 使用 toString.call() */ toString.call(function(){ }) // "[object Function]" toString.call(Function()) // "[object Function]" toString.call(new Function()) // "[object Function]" toString.call(undefined) // "[object Undefined]" toString.call(null) // "[object Null]" toString.call({}) // "[object Object]" toString.call([]) // "[object Array]" toString.call(new function(){}) // "[object Object]" toString.call("abc") // "[object String]" toString.call(123) // "[object Number]"
我的解决方案:
console.log(toString.call(bar) === "[object Object]");
2.
下面代码在 console 中输出什么?原因?
(function(){ var a = b = 3; })(); console.log("a defined? " + (typeof a !== 'undefined')); console.log("b defined? " + (typeof b !== 'undefined'));
引用
Since both a and b are defined within the enclosing scope of the function, and since the line they are on begins with the var keyword, most JavaScript developers would expect typeof a and typeof b to both be undefined in the above example.
However, that is not the case. The issue here is that most developers incorrectly understand the statement var a = b = 3; to be shorthand for:
var b = 3;
var a = b;
But in fact, var a = b = 3; is actually shorthand for:
b = 3;
var a = b;
As a result (if you are not using strict mode), the output of the code snippet would be:
a defined? false
b defined? true
But how can b be defined outside of the scope of the enclosing function? Well, since the statement var a = b = 3; is shorthand for the statements b = 3; and var a = b;, b ends up being a global variable (since it is not preceded by the var keyword) and is therefore still in scope even outside of the enclosing function.
Note that, in strict mode (i.e., with use strict), the statement var a = b = 3; will generate a runtime error of ReferenceError: b is not defined, thereby avoiding any headfakes/bugs that might othewise result. (Yet another prime example of why you should use use strict as a matter of course in your code!)
3.
下面代码在 console 中输出什么?原因?
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();
引用
The above code will output the following to the console:
outer func: this.foo = bar
outer func: self.foo = bar
inner func: this.foo = undefined
inner func: self.foo = bar
In the outer function, both this and self refer to myObject and therefore both can properly reference and access foo.
In the inner function, though, this no longer refers to myObject. As a result, this.foo is undefined in the inner function, whereas the reference to the local variable self remains in scope and is accessible there.
4.
把 JavaScript 文件中的源代码整个包在一个 function 块中的意义及原因?
引用
This is an increasingly common practice, employed by many popular JavaScript libraries (jQuery, Node.js, etc.). This technique creates a closure around the entire contents of the file which, perhaps most importantly, creates a private namespace and thereby helps avoid potential name clashes between different JavaScript modules and libraries.
Another feature of this technique is to allow for an easily referenceable (presumably shorter) alias for a global variable. This is often used, for example, in jQuery plugins. jQuery allows you to disable the $ reference to the jQuery namespace, using jQuery.noConflict(). If this has been done, your code can still use $ employing this closure technique, as follows:
(function($) { /* jQuery plugin code referencing $ */ } )(jQuery);
5.
在 JavaScript 文件的源代码的开头使用 'use strict' 的意义及益处?
引用
the short and most important answer here is that use strict is a way to voluntarily enforce stricter parsing and error handling on your JavaScript code at runtime. Code errors that would otherwise have been ignored or would have failed silently will now generate errors or throw exceptions. In general, it is a good practice.
Some of the key benefits of strict mode include:
Makes debugging easier. Code errors that would otherwise have been ignored or would have failed silently will now generate errors or throw exceptions, alerting you sooner to problems in your code and directing you more quickly to their source.
Prevents accidental globals. Without strict mode, assigning a value to an undeclared variable automatically creates a global variable with that name. This is one of the most common errors in JavaScript. In strict mode, attempting to do so throws an error.
Eliminates this coercion. Without strict mode, a reference to a this value of null or undefined is automatically coerced to the global. This can cause many headfakes and pull-out-your-hair kind of bugs. In strict mode, referencing a a this value of null or undefined throws an error.
Disallows duplicate property names or parameter values. Strict mode throws an error when it detects a duplicate named property in an object (e.g., var object = {foo: "bar", foo: "baz"};) or a duplicate named argument for a function (e.g., function foo(val1, val2, val1){}), thereby catching what is almost certainly a bug in your code that you might otherwise have wasted lots of time tracking down.
Makes eval() safer. There are some differences in the way eval() behaves in strict mode and in non-strict mode. Most significantly, in strict mode, variables and functions declared inside of an eval() statement are not created in the containing scope (they are created in the containing scope in non-strict mode, which can also be a common source of problems).
Throws error on invalid usage of delete. The delete operator (used to remove properties from objects) cannot be used on non-configurable properties of the object. Non-strict code will fail silently when an attempt is made to delete a non-configurable property, whereas strict mode will throw an error in such a case.
-
6.
下面两个函数返回值相同吗?为什么?
function foo1(){ return { bar: "hello" }; } function foo2(){ return { bar: "hello" }; }
引用
Surprisingly, these two functions will not return the same thing. Rather:
console.log("foo1 returns:");
console.log(foo1());
console.log("foo2 returns:");
console.log(foo2());
will yield:
foo1 returns:
Object {bar: "hello"}
foo2 returns:
undefined
Not only is this surprising, but what makes this particularly gnarly is that foo2() returns undefined without any error being thrown.
The reason for this has to do with the fact that semicolons are technically optional in JavaScript (although omitting them is generally really bad form). As a result, when the line containing the return statement (with nothing else on the line) is encountered in foo2(), a semicolon is automatically inserted immediately after the return statement.
No error is thrown since the remainder of the code is perfectly valid, even though it doesn’t ever get invoked or do anything (it is simply an unused code block that defines a property bar which is equal to the string "hello").
This behavior also argues for following the convention of placing an opening curly brace at the end of a line in JavaScript, rather than on the beginning of a new line. As shown here, this becomes more than just a stylistic preference in JavaScript.
结论:
javascript 中,分号是可选的。如果 return 语句的行尾没有分号,则自动加一个。
function f(){ var a = 10 var b = a + " Hello" console.log(b) }
象上面的代码,运行没有问题。
7.
什么是 NaN? 它是什么类型?如何判断一个值等价于 NaN ?
引用
The NaN property represents a value that is “not a number”. This special value results from an operation that could not be performed either because one of the operands was non-numeric (e.g., "abc" / 4), or because the result of the operation is non-numeric (e.g., an attempt to divide by zero).
While this seems straightforward enough, there are a couple of somewhat surprising characteristics of NaN that can result in hair-pulling bugs if one is not aware of them.
For one thing, although NaN means “not a number”, its type is, believe it or not, Number:
console.log(typeof NaN === "number"); // logs "true"
Additionally, NaN compared to anything – even itself! – is false:
console.log(NaN === NaN); // logs "false"
A semi-reliable way to test whether a number is equal to NaN is with the built-in function isNaN(), but even using isNaN() is an imperfect solution.
A better solution would either be to use value !== value, which would only produce true if the value is equal to NaN. Also, ES6 offers a new Number.isNaN() function, which is a different and more reliable than the old global isNaN() function.
8.What will the code below output? Explain your answer.
console.log(0.1 + 0.2); console.log(0.1 + 0.2 == 0.3); console.log(1.1 + 1.2 == 2.3);
引用
An educated answer to this question would simply be: “You can’t be sure. it might print out “0.3” and “true”, or it might not. Numbers in JavaScript are all treated with floating point precision, and as such, may not always yield the expected results.”
The example provided above is classic case that demonstrates this issue. Surprisingly, it will print out:
0.30000000000000004
false
tue
9.
Discuss possible ways to write a function isInteger(x) that determines if x is an integer.
引用
This may sound trivial and, in fact, it is trivial with ECMAscript 6 which introduces a new Number.isInteger() function for precisely this purpose. However, prior to ECMAScript 6, this is a bit more complicated, since no equivalent of the Number.isInteger() method is provided.
The issue is that, in the ECMAScript specification, integers only exist conceptually; i.e., numeric values are always stored as floating point values.
With that in mind, the simplest and cleanest pre-ECMAScript-6 solution (which is also sufficiently robust to return false even if a non-numeric value such as a string or null is passed to the function) would be the following:
function isInteger(x) { return (x^0) === x; }
The following solution would also work, although not as elegant as the one above:
function isInteger(x) { return Math.round(x) === x; }
Note that Math.ceil() or Math.floor() could be used equally well (instead of Math.round()) in the above implementation.
Or alternatively:
function isInteger(x) { return (typeof x === 'number') && (x % 1 === 0); }
One fairly common incorrect solution is the following:
function isInteger(x) { return parseInt(x, 10) === x; }
While this parseInt-based approach will work well for many values of x, once x becomes quite large, it will fail to work properly. The problem is that parseInt() coerces its first parameter to a string before parsing digits. Therefore, once the number becomes sufficiently large, its string representation will be presented in exponential form (e.g., 1e+21). Accordingly, parseInt() will then try to parse 1e+21, but will stop parsing when it reaches the e character and will therefore return a value of 1. Observe:
> String(1000000000000000000000)
'1e+21'
> parseInt(1000000000000000000000, 10)
1
> parseInt(1000000000000000000000, 10) === 1000000000000000000000
false
10.
In what order will the numbers 1-4 be logged to the console when the code below is executed? Why?
(function() { console.log(1); setTimeout(function(){console.log(2)}, 1000); setTimeout(function(){console.log(3)}, 0); console.log(4); })();
引用
The values will be logged in the following order:
1
4
3
2
Let’s first explain the parts of this that are presumably more obvious:
1 and 4 are displayed first since they are logged by simple calls to console.log() without any delay
2 is displayed after 3 because 2 is being logged after a delay of 1000 msecs (i.e., 1 second) whereas 3 is being logged after a delay of 0 msecs.
OK, fine. But if 3 is being logged after a delay of 0 msecs, doesn’t that mean that it is being logged right away? And, if so, shouldn’t it be logged before 4, since 4 is being logged by a later line of code?
The answer has to do with properly understanding JavaScript events and timing.
The browser has an event loop which checks the event queue and processes pending events. For example, if an event happens in the background (e.g., a script onload event) while the browser is busy (e.g., processing an onclick), the event gets appended to the queue. When the onclick handler is complete, the queue is checked and the event is then handled (e.g., the onload script is executed).
Similarly, setTimeout() also puts execution of its referenced function into the event queue if the browser is busy.
When a value of zero is passed as the second argument to setTimeout(), it attempts to execute the specified function “as soon as possible”. Specifically, execution of the function is placed on the event queue to occur on the next timer tick. Note, though, that this is not immediate; the function is not executed until the next tick. That’s why in the above example, the call to console.log(4) occurs before the call to console.log(3) (since the call to console.log(3) is invoked via setTimeout, so it is slightly delayed).
11.
Write a simple function (less than 80 characters) that returns a boolean indicating whether or not a string is a palindrome.
引用
The following one line function will return true if str is a palindrome; otherwise, it returns false.
function isPalindrome(str) {
str = str.replace(/\W/g, '').toLowerCase();
return (str == str.split('').reverse().join(''));
}
For example:
console.log(isPalindrome("level")); // logs 'true'
console.log(isPalindrome("levels")); // logs 'false'
console.log(isPalindrome("A car, a man, a maraca")); // logs 'true'
12.
Write a sum method which will work properly when invoked using either syntax below.
console.log(sum(2,3)); // Outputs 5
console.log(sum(2)(3)); // Outputs 5
引用
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; };
}
}
In JavaScript, functions provide access to an arguments object which provides access to the actual arguments passed to a function. This enables us to use the length property to determine at runtime the number of arguments passed to the function.
If two arguments are passed, we simply add them together and return.
Otherwise, we assume it was called in the form sum(2)(3), so we return an anonymous function that adds together the argument passed to sum() (in this case 2) and the argument passed to the anonymous function (in this case 3).
METHOD 2
function sum(x, y) {
if (y !== undefined) {
return x + y;
} else {
return function(y) { return x + y; };
}
}
When a function is invoked, JavaScript does not require the number of arguments to match the number of arguments in the function definition. If the number of arguments passed exceeds the number of arguments in the function definition, the excess arguments will simply be ignored. On the other hand, if the number of arguments passed is less than the number of arguments in the function definition, the missing arguments will have a value of undefined when referenced within the function. So, in the above example, by simply checking if the 2nd argument is undefined, we can determine which way the function was invoked and proceed accordingly.
13.
Consider 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); }
(a) What gets logged to the console when the user clicks on “Button 4” and why?
(b) Provide one or more alternate implementations that will work as expected.
引用
(a) No matter what button the user clicks the number 5 will always be logged to the console. This is because, at the point that the onclick method is invoked (for any of the buttons), the for loop has already completed and the variable i already has a value of 5. (Bonus points for the interviewee if they know enough to talk about how execution contexts, variable objects, activation objects, and the internal “scope” property contribute to the closure behavior.)
(b) The key to making this work is to capture the value of i at each pass through the for loop by passing it into a newly created function object. Here are three possible ways to accomplish 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);
}
Alternatively, you could wrap the entire call to btn.addEventListener in the 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);
}
Or, we could replace the for loop with a call to the array object’s native forEach method:
['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);
});
14.
What will the code below 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));
引用
The logged output will be:
"array 1: length=5 last=j,o,n,e,s"
"array 2: length=5 last=j,o,n,e,s"
arr1 and arr2 are the same after the above code is executed for the following reasons:
Calling an array object’s reverse() method doesn’t only return the array in reverse order, it also reverses the order of the array itself (i.e., in this case, arr1).
The reverse() method returns a reference to the array itself (i.e., in this case, arr1). As a result, arr2 is simply a reference to (rather than a copy of) arr1. Therefore, when anything is done to arr2 (i.e., when we invoke arr2.push(arr3);), arr1 will be affected as well since arr1 and arr2 are simply references to the same object.
And a couple of side points here that can sometimes trip someone up in answering this question:
Passing an array to the push() method of another array pushes that entire array as a single element onto the end of the array. As a result, the statement arr2.push(arr3); adds arr3 in its entirety as a single element to the end of arr2 (i.e., it does not concatenate the two arrays, that’s what the concat() method is for).
Like Python, JavaScript honors negative subscripts in calls to array methods like slice() as a way of referencing elements at the end of the array; e.g., a subscript of -1 indicates the last element in the array, and so on.
15.
What will the code below 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);
引用
The above code will output the following to the console:
"122"
"32"
"02"
"112"
"NaN2"
NaN
Here’s why…
The fundamental issue here is that JavaScript (ECMAScript) is a loosely typed language and it performs automatic type conversion on values to accommodate the operation being performed. Let’s see how this plays out with each of the above examples.
Example 1: 1 + "2" + "2" Outputs: "122" Explanation: The first operation to be performed in 1 + "2". Since one of the operands ("2") is a string, JavaScript assumes it needs to perform string concatenation and therefore converts the type of 1 to "1", 1 + "2" yields "12". Then, "12" + "2" yields "122".
Example 2: 1 + +"2" + "2" Outputs: "32" Explanation: Based on order of operations, the first operation to be performed is +"2" (the extra + before the first "2" is treated as a unary operator). Thus, JavaScript converts the type of "2" to numeric and then applies the unary + sign to it (i.e., treats it as a positive number). As a result, the next operation is now 1 + 2 which of course yields 3. But then, we have an operation between a number and a string (i.e., 3 and "2"), so once again JavaScript converts the type of the numeric value to a string and performs string concatenation, yielding "32".
Example 3: 1 + -"1" + "2" Outputs: "02" Explanation: The explanation here is identical to the prior example, except the unary operator is - rather than +. So "1" becomes 1, which then becomes -1 when the - is applied, which is then added to 1 yielding 0, which is then converted to a string and concatenated with the final "2" operand, yielding "02".
Example 4: +"1" + "1" + "2" Outputs: "112" Explanation: Although the first "1" operand is typecast to a numeric value based on the unary + operator that precedes it, it is then immediately converted back to a string when it is concatenated with the second "1" operand, which is then concatenated with the final "2" operand, yielding the string "112".
Example 5: "A" - "B" + "2" Outputs: "NaN2" Explanation: Since the - operator can not be applied to strings, and since neither "A" nor "B" can be converted to numeric values, "A" - "B" yields NaN which is then concatenated with the string "2" to yield “NaN2”.
Example 6: "A" - "B" + 2 Outputs: NaN Explanation: As exlained in the previous example, "A" - "B" yields NaN. But any operator applied to NaN with any other numeric operand will still yield NaN.
16.
The following recursive code will cause a stack overflow if the array list is too large. How can you fix this and still retain the recursive pattern?
var list = readHugeList(); var nextListItem = function() { var item = list.pop(); if (item) { // process the list item... nextListItem(); } };
引用
The potential stack overflow can be avoided by modifying the nextListItem function as follows:
var list = readHugeList();
var nextListItem = function() {
var item = list.pop();
if (item) {
// process the list item...
setTimeout( nextListItem, 0);
}
};
The stack overflow is eliminated because the event loop handles the recursion, not the call stack. When nextListItem runs, if item is not null, the timeout function (nextListItem) is pushed to the event queue and the function exits, thereby leaving the call stack clear. When the event queue runs its timed-out event, the next item is processed and a timer is set to again invoke nextListItem. Accordingly, the method is processed from start to finish without a direct recursive call, so the call stack remains clear, regardless of the number of iterations.
17.
What is a “closure” in JavaScript? Provide an example.
引用
A closure is an inner function that has access to the variables in the outer (enclosing) function’s scope chain. The closure has access to variables in three scopes; specifically: (1) variable in its own scope, (2) variables in the enclosing function’s scope, and (3) global variables.
Here is 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);
In the above example, variables from innerFunc, outerFunc, and the global namespace are all in scope in the innerFunc. The above code will therefore produce the following output:
outerArg = 123
innerArg = 456
outerVar = a
innerVar = b
globalVar = xyz
18.
What will be the output of the following code:
for (var i = 0; i < 5; i++) { setTimeout(function() { console.log(i); }, i * 1000 ); }
Explain your answer. How could the use of closures help here?
引用
The code sample shown will not display the values 0, 1, 2, 3, and 4 as might be expected; rather, it will display 5, 5, 5, 5, and 5.
The reason for this is that each function executed within the loop will be executed after the entire loop has completed and all will therefore reference the last value stored in i, which was 5.
Closures can be used to prevent this problem by creating a unique scope for each iteration, storing each unique value of the variable within its scope, as follows:
for (var i = 0; i < 5; i++) {
(function(x) {
setTimeout(function() { console.log(x); }, x * 1000 );
})(i);
}
This will produce the presumably desired result of logging 0, 1, 2, 3, and 4 to the console.
19.
What would the following lines of 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));
Explain your answer.
引用
The code will output the following four lines:
0 || 1 = 1
1 || 2 = 1
0 && 1 = 0
1 && 2 = 2
In JavaScript, both || and && are logical operators that return the first fully-determined “logical value” when evaluated from left to right.
The or (||) operator. In an expression of the form X||Y, X is first evaluated and interpreted as a boolean value. If this boolean value is true, then true (1) is returned and Y is not evaluated, since the “or” condition has already been satisfied. If this boolean value is “false”, though, 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.
Accordingly, 0 || 1 evaluates to true (1), as does 1 || 2.
The and (&&) operator. In an expression of the form X&&Y, X is first evaluated and interpreted as a boolean value. If this boolean value is false, then false (0) is returned and Y is not evaluated, since the “and” condition has already failed. If this boolean value is “true”, though, 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 with the && operator is that when an expression is evaluated as “true”, then the expression itself is returned. This is fine, since it counts as “true” in logical expressions, but also can be used to return that value when you care to do so. This explains why, somewhat surprisingly, 1 && 2 returns 2 (whereas you might it expect it to return true or 1).
20.
What will be the output when the following code is executed? Explain.
console.log(false == '0') console.log(false === '0')
引用
The code will output:
true
false
In JavaScript, there are two sets of equality operators. The triple-equal operator === behaves like any traditional equality operator would: evaluates to true if the two expressions on either of its sides have the same type and the same value. The double-equal operator, however, tries to coerce the values before comparing them. It is therefore generally good practice to use the === rather than ==. The same holds true for !== vs !=.
21.
What is the output out of the following code? Explain your answer.
var a={}, b={key:'b'}, c={key:'c'}; a[b]=123; a[c]=456; console.log(a[b]);
引用
The output of this code will be 456 (not 123).
The reason for this is as follows: When setting an object property, JavaScript will implicitly stringify the parameter value. In this case, since b and c are both objects, they will both be converted to "[object Object]". As a result, a[b] anda[c] are both equivalent to a["[object Object]"] and can be used interchangeably. Therefore, setting or referencing a[c] is precisely 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));Explain your answer.
引用
The code will output the value of 10 factorial (i.e., 10!, or 3,628,800).
Here’s why:
The named function f() calls itself recursively, until it gets down to calling f(1) which simply returns 1. Here, therefore, is what this does:
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 3628800
23.
Consider the code snippet below. What will the console output be and why?
(function(x) { return (function(y) { console.log(x); })(2) })(1);
引用
The output will be 1, even though the value of x is never set in the inner function. Here’s why:
As explained in our JavaScript Hiring Guide, a closure is a function, along with all variables or functions that were in-scope at the time that the closure was created. In JavaScript, a closure is implemented as an “inner function”; i.e., a function defined within the body of another function. An important feature of closures is that an inner function still has access to the outer function’s variables.
Therefore, in this example, since x is not defined in the inner function, the scope of the outer function is searched for a defined variable x, which is found to have a value of 1.
24.
What will the following code output 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());
What is the issue with this code and how can it be fixed.
引用
The code will output:
undefined
John Doe
The first console.log prints undefined because we are extracting the method from the hero object, so stoleSecretIdentity() is being invoked in the global context (i.e., 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);
25.
Create a function that, given a DOM Element on the page, will visit the element itself and all of its descendents (not just its immediate children). For each element visited, the function should pass that element to a provided callback function.
The arguments to the function should be:
a DOM element
a callback function (that takes a DOM element as its argument)
引用
Visiting all elements in a tree (DOM) is a classic Depth-First-Search algorithm application. Here’s an example 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
}
}
-
引自:
https://www.toptal.com/javascript/interview-questions
-
发表评论
-
Javascript 测试框架之 隐式声明 之 describe
2019-06-25 15:26 2578为什么使用 javascript 测试框架时,没有显式导入 d ... -
JavaScript之ECMAScript6新特性之_03_箭头函数(Arrow Function)
2018-01-25 13:46 1116一、简介 箭头函数(Arrow Function)是 ES6 ... -
JavaScript之ECMAScript6新特性之_02_线程异步阻塞: Promise, Async / await
2018-01-12 16:51 2322刚出来不久的 ES8 包含了 async 函数,它的出现,终于 ... -
JavaScript之ECMAScript6新特性之_01_开篇
2017-08-17 02:54 602点此查看全部: http://es6-features.org ... -
jQuery Versions - browser support
2017-08-12 04:19 1610jQuery 3.2.1 Support Deskto ... -
基于HTML5实现的中国象棋游戏
2017-06-24 02:24 1681HTML5实现中国象棋游戏 http://www.w2bc.c ... -
JavaScript之跨域请求解决方案
2017-06-07 11:03 3967浏览器处于安全原因,在使用 Ajax 进行请求访问时,不允许跨 ... -
JavaScript小应用之分页算法
2017-03-16 12:56 663效果图: function getPagina ... -
jQuery之empty() VS. remove()
2017-03-16 10:32 719jQuery empty() vs remove() Wh ... -
jQuery之 prop() VS. attr()
2017-03-14 16:43 656attr() 用于自定义属性,id ; prop() 用于 ... -
jQuery之mouseover,mouseover,mouseout,mouseleave
2017-03-14 10:20 653Jquery mouseenter() vs mouseove ... -
javascript之JS操作iframe
2017-02-28 14:56 2191JS操作iframe 1. 获得iframe的w ... -
javascript之面向对象编程之原型继承
2017-01-02 15:34 1116前文讲到“属性继承” ... -
HTML5之Cookie,localStorage 与 sessionStorage
2016-12-22 18:35 842详说 Cookie, LocalStorage 与 ... -
jquery之live(), delegate(), on() 方法
2016-11-26 23:48 925通过下面的一个实例理解 jQuery 的 live(), de ... -
javascript之小应用:网页在线聊天
2016-11-08 11:48 4293概览 这款使用 PHP 和 javascript 搭建的 ... -
javascript之编程序题目
2016-11-06 17:30 10501. 判断两个字符串是否:字母相同切长度相同(空格不算)。 ... -
javascript之面向对象编程之属性继承
2016-10-23 21:09 885函数继承可以分为两种:1、继承其 this 属性 2、继承其 ... -
javascript 之 undefined
2016-08-12 11:01 703一、用法 undefined 关键字有两种用法: 1. 如 ... -
javascript之 == vs ===
2016-06-12 15:59 652一、Comparison Overview 1. Speed ...
相关推荐
JavaScript常见面试题
### JavaScript面试题解析 #### 一、ES6的新语法 ES6(ECMAScript 6)是JavaScript语言标准的一个重要版本,它引入了许多新的特性和语法改进,旨在提高开发效率和代码可读性。以下是一些重要的新特性: 1. **let ...
根据给定的信息,我们将深入分析并提取出与JavaScript面试题相关的知识点。 ### 一、单选题 #### 1. 以下哪条语句会产生运行错误: - **选项A**: `var obj = ();` - **解析**:在JavaScript中,括号`()`通常用于...
这700道JavaScript习题及面试题集合涵盖了JavaScript的基础语法、高级特性、DOM操作、BOM处理、Ajax、事件处理、函数、对象、闭包、原型链等多个方面,旨在帮助开发者深入理解和掌握JavaScript的精髓。 1. **基础...
JavaScript 60道面试题及答案.docx
18.md 5个典型的JavaScript面试题(上) JavaScript 19.md 再来5个JavaScript面试题 JavaScript 20.md BAT web前端开发方向校招都考些什么? General 21.md Eleme 笔试题 General 22.md 一些JS题目的解答 ...
JavaScript 60道面试题和答案.docx
JavaScript 50道面试题和答案.docx
JavaScript 面试题知识点总结 JavaScript 面试题是前端开发领域中常见的面试题,涵盖了 JavaScript 基础、Web 前端开发等方面的知识点。本文将对 JavaScript 面试题的知识点进行总结,包括 Object.create、...
"JavaScript面试题集锦详解" 这篇文章涵盖了JavaScript的多个方面,包括eval函数、window和document对象、null和undefined的区别、数组的map方法、事件机制、use strict模式等。 eval函数 eval函数可以将字符串...
Java面试题、设计模式面试题、Spring面试题、MyBatis面试题、Memcached面试题、MongoDB面试题、ZooKeepe面试题、RabbitMQ面试题、HTML面试题、CSS面试题、Vue面试题、React面试题、JavaScript面试题、2021java面试题...
这份“JavaScript面试题”文档旨在帮助你深入理解JavaScript的基础和高级概念,以便在面试中展现出扎实的技术功底。以下是一些关键的知识点,涵盖了标题和描述中提及的JavaScript面试重点。 1. **基本语法与数据...
面试题练习题前端 JavaScript高级语法-字符串属性面试题练习题前端 JavaScript高级语法-字符串属性面试题练习题前端 JavaScript高级语法-字符串属性面试题练习题前端 JavaScript高级语法-字符串属性面试题练习题前端...
大公司javaScript经典面试题汇总
JavaScript面试题汇总涵盖了广泛的知识点,以下是其中一些关键点的详细说明: 1. **变量声明**:在JavaScript中,可以使用var关键字声明变量。在给定的题目中,选项A `( )` 是一个无效的声明,因为没有提供任何值,...
2022年面试题,Java基础面试题、JVM面试题、并发编程与线程面试题、设计模式面试题、SpringBoot面试题、SpringCloud面试题、MyBatis面试题、Redis面试题等。包括Java基础、Java集合、Java并发、JVM、Java WEB、设计...
JavaScript进阶面试题_30题.pdf_前端面试题 从这份文件中,我们可以总结出以下的知识点: 1. ECMAScript6 中的类语法糖:ECMAScript6 中引入了类语法糖,这使得有 OOP 基础的人更容易上手 JavaScript。虽然对熟悉 ...