Common JavaScript face questions

1, using typeof bar === "object" judgment bar of God is not an object horse potential drawbacks? How to avoid this abuse?

Use typeof drawbacks are obvious (such drawbacks with the use of instanceof):

let obj = {};
let arr = [];

console.log(typeof obj === 'object');  //true
console.log(typeof arr === 'object');  //true
console.log(typeof null === 'object');  //true

It is seen from the above output, typeof bar === "object", and can not accurately determine that a bar Object. You can  Object.prototype.toString.call(bar) === "[object Object]" avoid such drawbacks to:

let obj = {};
let arr = [];

console.log(Object.prototype.toString.call(obj));  //[object Object]
console.log(Object.prototype.toString.call(arr));  //[object Array]
console.log(Object.prototype.toString.call(null));  //[object Null]

In addition, to cherish life, please stay away from ==:
cherish life

And [] is false === returns false.

2, the following code will output god horse in console? why?

(function(){
  var a = b = 3;
})();

console.log("a defined? " + (typeof a !== 'undefined'));   
console.log("b defined? " + (typeof b !== 'undefined'));

这跟变量作用域有关,输出换成下面的:

console.log(b); //3
console,log(typeof a); //undefined

拆解一下自执行函数中的变量赋值:

b = 3;
var a = b;

所以 b 成了全局变量,而 a 是自执行函数的一个局部变量。

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 first and second output not difficult to determine, before ES6, JavaScript only function scope, so the func in IIFE have their own independent scope, and it has access to external self scope, so the third output will complain, because this can be accessed in the scope is undefined, the fourth output is bar. If you know the closures, and very easy to resolve:

(function(test) {
            console.log("inner func:  this.foo = " + test.foo);  //'bar'
            console.log("inner func:  self.foo = " + self.foo);
}(self));

If you are not familiar with the closures, you can stamp this: talk about closure from the scope chain

4, the JavaScript code in a function block God horse mean? Why should I do?

In other words, why should perform the function expression (Immediately-Invoked Function Expression) immediately.

There are two more classic IIFE usage scenario, similar to one cycle of the output timing of the data item, and the two plug-in module development is similar JQuery / Node's.

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

Above output not you think of 0,1,2,3,4, and all output is 5, then you can IIFE useful:

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

The plug-in module development and JQuery / Node in order to avoid contamination of variables, is also a big IIFE:

(function ($) { 
         // Code 
 }) (jQuery);

5, the horse God JavaScript development benefits in strict mode ( 'use strict') under?

消除Javascript语法的一些不合理、不严谨之处,减少一些怪异行为;
消除代码运行的一些不安全之处,保证代码运行的安全;
提高编译器效率,增加运行速度;
为未来新版本的Javascript做好铺垫。

6、下面两个函数的返回值是一样的吗?为什么?

function foo1()
{
  return {
      bar: "hello"
  };
}

function foo2()
{
  return
  {
      bar: "hello"
  };
}

在编程语言中,基本都是使用分号(;)将语句分隔开,这可以增加代码的可读性和整洁性。而在JS中,如若语句各占独立一行,通常可以省略语句间的分号(;),JS 解析器会根据能否正常编译来决定是否自动填充分号:

var test = 1 + 2;
console.log(test);  //3

在上述情况下,为了正确解析代码,就不会自动填充分号了,但是对于 return 、break、continue 等语句,如果后面紧跟换行,解析器一定会自动在后面填充分号(;),所以上面的第二个函数就变成了这样:

function foo2()
{
  return;
  {
      bar: "hello"
  };
}

所以第二个函数是返回 undefined。

7、神马是 NaN,它的类型是神马?怎么测试一个值是否等于 NaN?

NaN 是 Not a Number 的缩写,JavaScript 的一种特殊数值,其类型是 Number,可以通过 isNaN(param) 来判断一个值是否是 NaN:

console.log(isNaN(NaN)); //true
console.log(isNaN(23)); //false
console.log(isNaN('ds')); //true
console.log(isNaN('32131sdasd')); //true
console.log(NaN === NaN); //false
console.log(NaN === undefined); //false
console.log(undefined === undefined); //false
console.log(typeof NaN); //number
console.log(Object.prototype.toString.call(NaN)); //[object Number]

ES6 中,isNaN() 成为了 Number 的静态方法:Number.isNaN().

8、解释一下下面代码的输出

console.log(0.1 + 0.2);   //0.30000000000000004
console.log(0.1 + 0.2 == 0.3);  //false

JavaScript 中的 number 类型就是浮点型,JavaScript 中的浮点数采用IEEE-754 格式的规定,这是一种二进制表示法,可以精确地表示分数,比如1/2,1/8,1/1024,每个浮点数占64位。但是,二进制浮点数表示法并不能精确的表示类似0.1这样 的简单的数字,会有舍入误差。

由于采用二进制,JavaScript 也不能有限表示 1/10、1/2 等这样的分数。在二进制中,1/10(0.1)被表示为 0.00110011001100110011…… 注意 0011 是无限重复的,这是舍入误差造成的,所以对于 0.1 + 0.2 这样的运算,操作数会先被转成二进制,然后再计算:

0.1 => 0.0001 1001 1001 1001…(无限循环) 0.2 => 0.0011 0011 0011 0011…(无限循环)

双精度浮点数的小数部分最多支持 52 位,所以两者相加之后得到这么一串 0.0100110011001100110011001100110011001100...因浮点数小数位的限制而截断的二进制数字,这时候,再把它转换为十进制,就成了 0.30000000000000004。

对于保证浮点数计算的正确性,有两种常见方式:

一是先升幂再降幂:

function add(num1, num2){
  let r1, r2, m;
  r1 = (''+num1).split('.')[1].length;
  r2 = (''+num2).split('.')[1].length;

  m = Math.pow(10,Math.max(r1,r2));
  return (num1 * m + num2 * m) / m;
}
console.log(add(0.1,0.2));   //0.3
console.log(add(0.15,0.2256)); //0.3756

二是是使用内置的 toPrecision() 和 toFixed() 方法,注意,方法的返回值字符串。

function add(x, y) {
    return x.toPrecision() + y.toPrecision()
}
console.log(add(0.1,0.2));  //"0.10.2"

9、实现函数 isInteger(x) 来判断 x 是否是整数

可以将 x 转换成10进制,判断和本身是不是相等即可:

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

ES6 对数值进行了扩展,提供了静态方法 isInteger() 来判断参数是否是整数:

Number.isInteger(25) // true
Number.isInteger(25.0) // true
Number.isInteger(25.1) // false
Number.isInteger("15") // false
Number.isInteger(true) // false

JavaScript能够准确表示的整数范围在 -2^53 到 2^53 之间(不含两个端点),超过这个范围,无法精确表示这个值。ES6 引入了Number.MAX_SAFE_INTEGER 和 Number.MIN_SAFE_INTEGER这两个常量,用来表示这个范围的上下限,并提供了 Number.isSafeInteger() 来判断整数是否是安全型整数。

10、在下面的代码中,数字 1-4 会以什么顺序输出?为什么会这样输出?

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

This is not to explain, is mainly timing mechanism and the time cycle of JavaScript, do not forget, JavaScript is single-threaded. Detailed talk JavaScript can refer to the operating mechanism from setTimeout.

11. Write a function of fewer than 80 characters, the string is not a palindrome judge a string

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

I came across this question on codewars too, and included some nice solution, you can poke here: Palindrome For Your Dome

12, write a call to sum method can work properly in the following manner

console.log(sum(2,3));   // Outputs 5
console.log(sum(2)(3));  // Outputs 5

To address this problem, we can determine the number of parameters to achieve:

function sum() {
  var fir = arguments[0];
  if(arguments.length === 2) {
    return arguments[0] + arguments[1]
  } else {
    return function(sec) {
       return fir + sec;
    }
  }

}

13, answer questions later according to the following code fragment

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);
}

1. Click Button 4, what will output in the console?
2, give a line with expected implementation

A: 1, click on any one of the five buttons are Output 5
2, reference IIFE.

14, the following code will output what? why?

var arr1 = "john".split(''); j o h n
var arr2 = arr1.reverse(); n h o j
var arr3 = "jones".split(''); j o n e s
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));

会输出什么呢?你运行下就知道了,可能会在你的意料之外。

MDN 上对于 reverse() 的描述是酱紫的:

Description
The reverse method transposes the elements of the calling array object in place, mutating the array, and returning a reference to the array.

reverse() 会改变数组本身,并返回原数组的引用。

slice 的用法请参考:slice

15、下面的代码会输出什么?为什么?

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);

What is the output of their own to run it, you need to pay attention to three points:

1, a plurality of strings of digital and digital mixing operation, with the position of the relevant operands

console.log(2 + 1 + '3'); / /‘33’
console.log('3' + 2 + 1); //'321'

In the presence of a digital sign (+/-) prior to the numeric string, it is converted into a digital

console.log(typeof '3');   // string
console.log(typeof +'3');  //number

Similarly, you can be added before the number ', the number to a string.

2、

console.log(typeof 3);   // number
console.log(typeof (''+3));  //string

For the calculation result can not be converted to digital, and NaN

console.log('a' * 'sd');   //NaN
console.log('A' - 'B');  // NaN

This map is a regular expression conversion

3, the conversion operator

16, if the list is large, the following code would cause this recursive stack overflow. If rehabilitated this code without changing the recursive pattern premise?

var list = readHugeList();

var nextListItem = function() {
    var item = list.pop();

    if (item) {
        // process the list item...
        nextListItem();
    }
};

On the original solution is to add a timer:

var list = readHugeList();

var nextListItem = function() {
    var item = list.pop();

    if (item) {
        // process the list item...
        setTimeout( nextListItem, 0);
    }
};

Please refer to the principles of solution of the question 10.

17, what is closure? for example

Can refer to this post: On closure from the scope chain

18, the following code will output what? Why?

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

Please Wang Qianmian turn, refer to question 4, the solution is already above

19, the following explains the output code

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

逻辑与和逻辑或运算符会返回一个值,并且二者都是短路运算符:

逻辑与返回第一个是 false 的操作数 或者 最后一个是 true的操作数

console.log(1 && 2 && 0);  //0
console.log(1 && 0 && 1);  //0
console.log(1 && 2 && 3);  //3

如果某个操作数为 false,则该操作数之后的操作数都不会被计算

逻辑或返回第一个是 true 的操作数 或者 最后一个是 false的操作数

console.log(1 || 2 || 0); //1
console.log(0 || 2 || 1); //2
console.log(0 || 0 || false); //false

如果某个操作数为 true,则该操作数之后的操作数都不会被计算

如果逻辑与和逻辑或作混合运算,则逻辑与的优先级高:

console.log(1 && 2 || 0); //2
console.log(0 || 2 && 1); //1
console.log(0 && 2 || 1); //1

In JavaScript, a common false values:

Empty array is to be noted ([]) and the null object ({}):

console.log([] == false) //true
console.log({} == false) //false
console.log(Boolean([])) //true
console.log(Boolean({})) //true

If so, the [] {} have shown and is true:

20, the following explains the output code

console.log(false == '0')
console.log(false === '0')

请参考前面第14题运算符转换规则的图。

21、解释下面代码的输出

var a={},
    b={key:'b'},
    c={key:'c'};

a[b]=123;
a[c]=456;

console.log(a[b]);

输出是 456,参考原文的解释:

原因如下:设置对象属性时,javascript将隐式地将参数值字符串化。在这种情况下,因为B和C都是对象,所以它们都将被转换为“[对象对象]”。因此,a[b]和a[c]都相当于一个[“[对象对象]”],可以互换使用。因此,设置或引用A[C]与设置或引用A[B]完全相同。

22、解释下面代码的输出

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

The result is the factorial of 10. This is a recursive call, for simplicity we initialize n = 5, and return the call chain strand as follows:

Recursion

23, the following explains the output code

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

Output 1, the closure variable parameters can access external or scope.

24, interpret the output of the following code, and fix problems

var hero = {
    _name: 'John Doe',
    getSecretIdentity: function (){
        return this._name;
    }
};

var stoleSecretIdentity = hero.getSecretIdentity;

console.log(stoleSecretIdentity());
console.log(hero.getSecretIdentity());

The getSecretIdentity assigned stoleSecretIdentity, equivalent to the function defined stoleSecretIdentity:

var stoleSecretIdentity =  function (){
        return this._name;
}

stoleSecretIdentity context is the global environment, so the first output undefined. To output John Doe, will have changed by stoleSecretIdentity call, apply and bind other forms of this point (hero).

The second method is to call the object's output John Doe.

25, to give you a DOM elements, create a function that can access the elements of all sub-elements, and you want each sub-element is passed to the callback function specified.

Function accepts two parameters:

DOM
callback function specified
text using the depth-first search (Depth-First-Search) to a realization:

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.cnblogs.com/yzhihao/p/6530564.html

Guess you like

Origin www.cnblogs.com/wmrp/p/11071855.html