主流公司的21个JavaScript面试问题

21个基本JavaScript面试问题

21个基本JavaScript面试问题

问题1

1. undefinednot defined在JavaScript中有什么区别?

在JavaScript中,如果您尝试使用不存在且尚未声明的变量,则JavaScript将引发错误var name is not defined并且脚本将停止执行。但是,如果你使用typeof undeclared_variable,那么它将返回undefined

在进一步讨论之前,让我们先了解声明和定义之间的区别。

假设var x是一个声明,因为你还没有定义它所拥有的值,但你已经声明了它的存在以及内存分配的需要。

> var x; // declaring x
> console.log(x); //output: undefined 

var x = 1是一个声明和定义(我们也可以说我们正在进行初始化)。在上面的示例中,值的声明和赋值发生在变量x的内联中。在JavaScript中,调用您带到当前范围顶部的每个变量或函数声明hoisting

赋值按顺序发生,因此当我们尝试访问已声明但尚未定义的变量时,我们将得到结果undefined

var x; // Declaration
if(typeof x === 'undefined') // Will return true

如果一个既未声明也未定义的变量,当我们尝试引用这样的变量时,我们会得到结果not defined

> console.log(y);  // Output: ReferenceError: y is not defined

问题2

下面代码的输出是什么?

var y = 1;
  if (function f(){}) {
    y += typeof f;
  }
  console.log(y);

输出将是1undefined。该if条件语句计算使用eval,所以eval(function f(){})回报率function f(){}(这是真的)。因此,在if语句内部,由于语句代码在运行时执行,因此执行typeof f返回,并且在运行时评估条件内的语句。undefinedifif

var k = 1;
  if (1) {
    eval(function foo(){});
    k += typeof foo;
  }
  console.log(k); 

上面的代码也会输出1undefined

var k = 1;
  if (1) {
    function foo(){};
    k += typeof foo;
  }
  console.log(k); // output 1function

问题3

在JavaScript中创建真正的私有方法有什么缺点?

在JavaScript中创建真正的私有方法的一个缺点是它们的内存效率非常低,因为将为每个实例创建该方法的新副本。

var Employee = function (name, company, salary) {
    this.name = name || "";       //Public attribute default value is null
    this.company = company || ""; //Public attribute default value is null
    this.salary = salary || 5000; //Public attribute default value is null

    // Private method
    var increaseSalary = function () {
        this.salary = this.salary + 1000;
    };

    // Public method
    this.dispalyIncreasedSalary = function() {
        increaseSlary();
        console.log(this.salary);
    };
};

// Create Employee class object
var emp1 = new Employee("John","Pluto",3000);
// Create Employee class object
var emp2 = new Employee("Merry","Pluto",2000);
// Create Employee class object
var emp3 = new Employee("Ren","Pluto",2500);

这里的每个实例变量emp1emp2emp3有其自身的副本increaseSalary私有方法。

因此,作为建议,除非必要,否则不要使用私有方法。

 

问题4

什么是JavaScript中的“闭包”?举个例子

闭包是在另一个函数(称为父函数)中定义的函数,并且可以访问在父函数作用域中声明和定义的变量。

闭包可以访问三个范围中的变量:

  • 在自己的范围内声明的变量
  • 在父函数范围中声明的变量
  • 在全局命名空间中声明的变量
var globalVar = "abc"; 

// Parent self invoking function 
(function outerFunction (outerArg) { // begin of scope outerFunction
    // Variable declared in outerFunction function scope 
    var outerFuncVar = 'x';    
    // Closure self-invoking function 
    (function innerFunction (innerArg) { // begin of scope innerFunction
        // variable declared in innerFunction function scope
        var innerFuncVar = "y"; 
        console.log(          
            "outerArg = " + outerArg + "\n" +
            "outerFuncVar = " + outerFuncVar + "\n" +
            "innerArg = " + innerArg + "\n" +
            "innerFuncVar = " + innerFuncVar + "\n" +
            "globalVar = " + globalVar);
 
    }// end of scope innerFunction)(5); // Pass 5 as parameter 
}// end of scope outerFunction )(7); // Pass 7 as parameter 

innerFunction是在内部定义的闭包,outerFunction并且可以访问在outerFunction作用域中声明和定义的所有变量。另外,在另一个函数中定义的函数作为闭包将有权访问在中声明的变量global namespace

因此,上面代码的输出将是:

outerArg = 7
outerFuncVar = x
innerArg = 5
innerFuncVar = y
globalVar = abc

问题5

编写一个mul函数,在调用时将产生以下输出:

console.log(mul(2)(3)(4)); // output : 24 
console.log(mul(4)(3)(4)); // output : 48

下面是答案,然后解释它是如何工作的:

function mul (x) {
    return function (y) { // anonymous function 
        return function (z) { // anonymous function 
            return x * y * z; 
        };
    };
}

这里mul函数接受第一个参数并返回一个匿名函数,它接受第二个参数并返回另一个匿名函数,该函数将获取第三个参数并返回已传递的参数的乘法。

在JavaScript中,在另一个函数内定义的函数可以访问外部函数的变量。因此,函数是一个第一类对象,也可以由其他函数返回,并作为参数传递给另一个函数。

  • 函数是Object类型的实例
  • 函数可以具有属性,并具有返回其构造函数方法的链接
  • 函数可以存储为变量
  • 函数可以作为参数传递给另一个函数
  • 可以从另一个函数返回一个函数

 

问题6

如何在JavaScript中清空数组?

例如,

 var arrayList =  ['a','b','c','d','e','f'];

我们怎样才能清空上面的数组?

我们可以使用几种方法来清空数组,所以让我们讨论它们。

方法1

arrayList = []

上面的代码将变量设置arrayList为一个新的空数组。如果您在其他任何地方都没有对原始数组的引用, 则建议使用此方法arrayList,因为它实际上会创建一个新的空数组。您应该小心这种清空数组的方法,因为如果您从另一个变量引用了这个数组,那么原始引用数组将保持不变。

例如,

var arrayList = ['a','b','c','d','e','f']; // Created array 
var anotherArrayList = arrayList;  // Referenced arrayList by another variable 
arrayList = []; // Empty the array 
console.log(anotherArrayList); // Output ['a','b','c','d','e','f']

方法2

arrayList.length = 0;

上面的代码将通过将其长度设置为0来清除现有数组。这种清空数组的方式还会更新指向原始数组的所有引用变量。因此,当您想要更新指向的所有引用变量时,此方法很有用arrayList

例如,

var arrayList = ['a','b','c','d','e','f']; // Created array 
var anotherArrayList = arrayList;  // Referenced arrayList by another variable 
arrayList.length = 0; // Empty the array by setting length to 0
console.log(anotherArrayList); // Output []

方法3

arrayList.splice(0, arrayList.length);

上面的实现也将完美地运作。这种清空数组的方法也将更新对原始数组的所有引用。

var arrayList = ['a','b','c','d','e','f']; // Created array 
var anotherArrayList = arrayList;  // Referenced arrayList by another variable 
arrayList.splice(0, arrayList.length); // Empty the array by setting length to 0
console.log(anotherArrayList); // Output []

方法4

while(arrayList.length){
  arrayList.pop();
}

上面的实现也可以清空数组,但通常不建议经常使用此方法。

问题7

如何检查对象是否是数组?

找出对象是否是特定类的实例的最佳方法是使用以下toString方法Object.prototype

  var arrayList = [1,2,3];

类型检查对象的最佳用例之一是我们在JavaScript中进行方法重载。例如,假设我们有一个名为的方法greet,它接受一个字符串和一个字符串列表。为了使我们的greet方法在两种情况下都可行,我们需要知道传递的参数类型。它是单个值还是值列表?

function greet(param){
 	if(){ // here have to check whether param is array or not 
 	}else{
 	}
}

但是,由于上面的实现可能不一定检查数组的类型,我们可以检查单个值字符串并在else块中放入一些数组逻辑代码。例如:

function greet(param){
 	if(typeof param === 'string'){ 
 	}else{
 	  // If param is of type array then this block of code would execute
 	}
}

现在它的罚款,我们可与上述两种实现去,但是当我们遇到这样的情况该参数可以是single valuearrayobject类型,我们就会有麻烦。

回到检查对象的类型,如前所述,我们可以使用
Object.prototype.toString

if( Object.prototype.toString.call( arrayList ) === '[object Array]' ) {
    console.log('Array!');
}

如果您正在使用jQuery,那么您也可以使用jQuery isArray方法:

if($.isArray(arrayList)){
    console.log('Array');
}else{
  	console.log('Not an array');
}

仅供参考,jQuery在Object.prototype.toString.call内部使用来检查对象是否是数组。

在现代浏览器中,您也可以使用

Array.isArray(arrayList);

Array.isArray Chrome 5,Firefox 4.0,IE 9,Opera 10.5和Safari 5支持

问题8

以下代码的输出是什么?

var output = (function(x){
    delete x;
    return x;
  })(0);
  
  console.log(output);

输出将是0。的delete运算符用于从对象中删除属性。这x不是一个对象,而是一个局部变量delete运算符不会影响局部变量。

问题9

以下代码的输出是什么?

var x = 1;
var output = (function(){
    delete x;
    return x;
  })();
  
  console.log(output);

输出将是1。该delete操作是用来删除对象的属性。这x不是一个对象,而是它的全局变量类型number

问题10

下面代码的输出是什么?

var x = { foo : 1};
var output = (function(){
    delete x.foo;
    return x.foo;
  })();
  
  console.log(output);

输出将是undefined。该delete操作是用来删除对象的属性。这里,x是一个具有属性的对象foo,因为它是一个自调用函数,我们foo将从对象中删除该属性x。在这样做之后,当我们尝试引用已删除的属性时foo,结果是undefined

问题11

下面代码的输出是什么?

var Employee = {
  company: 'xyz'
}
var emp1 = Object.create(Employee);
delete emp1.company
console.log(emp1.company);

输出将是xyz。在这里,emp1对象都有company原型属性。该delete操作不会删除原型属性。

emp1对象没有公司作为自己的财产。你可以测试一下console.log(emp1.hasOwnProperty('company')); //output : false。但是,我们可以company直接从Employee对象中删除属性delete Employee.company。或者,我们也可以emp1使用__proto__属性删除对象delete emp1.__proto__.company

问题12

什么是undefined x 1JavaScript?

var trees = ["redwood","bay","cedar","oak","maple"];
delete trees[3];

当您运行上面的代码并输入console.log(trees);Chrome开发者控制台时,您将获得
["redwood", "bay", "cedar", undefined × 1, "maple"]。当您在Firefox的浏览器控制台中运行代码时,您将获得["redwood", "bay", "cedar", undefined, "maple"]。因此,很明显Chrome浏览器有自己的方式在数组中显示未初始化的索引。但是,当您同时检trees[3] === undefined入两个浏览器时,您将得到类似的输出true

注意:请记住,您不需要检查数组的未初始化索引 trees[3] === 'undefined × 1',因为它会给您一个错误。'undefined × 1'只是在Chrome中显示数组未初始化索引的方法。

问题13

下面代码的输出是什么?

var trees = ["xyz","xxxx","test","ryan","apple"];
delete trees[3];
  
  console.log(trees.length);

输出将是5。当我们使用delete运算符删除数组元素时,数组长度不受此影响。即使您使用delete运算符删除了数组的所有元素,这也成立。

换句话说,当delete运算符删除数组元素时,该数组中不再存在该已删除元素。代替值在删除的索引undefined x 1undefined被放置在索引处。如果您在Chrome和Firefox中console.log(trees)输出。["xyz", "xxxx", "test", undefined × 1, "apple"]["xyz", "xxxx", "test", undefined, "apple"]

问题14

下面代码的输出是什么?

var bar = true;
console.log(bar + 0);   
console.log(bar + "xyz");  
console.log(bar + true);  
console.log(bar + false);   

代码将输出1, "truexyz", 2, 1。以下是添加运算符的一般准则:

  • 数字+数字 - >加法
  • 布尔+数字 - >加法
  • 布尔+数字 - >加法
  • 数字+字符串 - >连接
  • String + Boolean - > Concatenation
  • String + String - > Concatenation

问题15

下面代码的输出是什么?

var z = 1, y = z = typeof y;
console.log(y);  

输出将是undefined。根据associativity规则,具有相同优先级的运算符基于运算符的关联属性进行处理。在这里,赋值运算符的结合性Right to Left,所以typeof y会先评估,这是undefined。它将被分配给z,然后y将被赋值为z,然后z将赋值1

问题16

下面代码的输出是什么?

// NFE (Named Function Expression 
var foo = function bar(){ return 12; };
typeof bar();  

输出将是Reference Error。要使上面的代码工作,您可以按如下方式重写它:

样品1

var bar = function(){ return 12; };
typeof bar();  

要么

样本2

function bar(){ return 12; };
typeof bar();  

函数定义只能有一个引用变量作为其函数名。在示例1中bar的引用变量指向anonymous function。在示例2中,函数的定义是名称函数。

var foo = function bar(){ 
    // foo is visible here 
    // bar is visible here
 	console.log(typeof bar()); // Work here :)
 };
// foo is visible here
// bar is undefined here

问题17

下面的函数声明有什么区别?

var foo = function(){ 
    // Some code
}; 
function bar(){ 
    // Some code
}; 

主要区别在于foo定义了函数,run-time而函数bar是在解析时定义的。为了更好地理解这一点,让我们看看下面的代码:

Run-Time function declaration 
<script>
foo(); // Calling foo function here will give an Error
  var foo = function(){ 
    console.log("Hi I am inside Foo");
 }; 
 </script>
<script>
Parse-Time function declaration 
bar(); // Calling foo function will not give an Error
 function bar(){ 
  console.log("Hi I am inside Foo");
 }; 
</script>

这种第一种声明方式的另一个优点是您可以根据特定条件声明函数。例如:

<script>
if(testCondition) {// If testCondition is true then 
   var foo = function(){ 
    console.log("inside Foo with testCondition True value");
   }; 
 }else{
 	 var foo = function(){ 
    console.log("inside Foo with testCondition false value");
   }; 
}
</script>

但是,如果您尝试使用以下格式运行类似的代码,则会出现错误:

<script>
if(testCondition) {// If testCondition is true then 
   function foo(){ 
    console.log("inside Foo with testCondition True value");
   }; 
 }else{
 	 function foo(){ 
    console.log("inside Foo with testCondition false value");
   }; 
}
</script>

问题18

什么是JavaScript中的函数提升?

功能表达

var foo = function foo(){ 
 	return 12; 
}; 

在JavaScript中,变量和函数是hoisted。让我们hoisting先把功能。基本上,JavaScript解释器会向前查找所有变量声明,然后将它们提升到声明它们的函数的顶部。例如:

foo(); // Here foo is still undefined 
var foo = function foo(){ 
 	return 12; 
}; 

在上面的代码的场景后面看起来像这样:

var foo = undefined;
    foo(); // Here foo is undefined 
 	   foo = function foo(){
 	      / Some code stuff
      }
var foo = undefined;
 	 foo = function foo(){
 	     / Some code stuff
    }
    foo(); // Now foo is defined here

问题19

下面的代码输出是什么?

var salary = "1000$";

 (function () {
     console.log("Original salary was " + salary);

     var salary = "5000$";

     console.log("My New Salary " + salary);
})();

输出将是undefined, 5000$。新手常常被JavaScript的提升概念所欺骗。在上面的代码中,您可能希望salary从外部作用域保留其值,直到salary在内部作用域中重新声明的点。但是,由于hoisting,工资价值是undefined相反的。要更好地理解这一点,请查看以下代码:

var salary = "1000$";

(function () {
    var salary = undefined;
    console.log("Original salary was " + salary);

    salary = "5000$";

    console.log("My New Salary " + salary);
})();

salary变量在函数范围的顶部被提升并声明。该console.log内部回报率undefined。之后console.logsalary重新申报并分配5000$

问题20

instanceofJavaScript中的运算符是什么?下面代码的输出是什么?

function foo(){ 
  return foo; 
}
new foo() instanceof foo;

这里,instanceof运算符检查当前对象,如果对象是指定类型,则返回true。

例如:

var dog = new Animal();
dog instanceof Animal // Output : true

dog instanceof Animal是真的,因为dog继承自Animal.prototype

var name = new String("xyz");
name instanceof String // Output : true

name instanceof String是真的,因为dog继承自String.prototype。现在让我们理解下面的代码:

function foo(){ 
  return foo; 
}
new foo() instanceof foo;

这里函数foo返回foo,再次指向函数foo

function foo(){
  return foo; 
}
var bar = new foo();
// here bar is pointer to function foo(){return foo}.

所以new foo() instanceof foo回归false;

参考链接

问题21

如果我们有一个JavaScript关联数组

var counterArray = {
    A : 3,
  	B : 4
};
counterArray["C"] = 1;

我们如何计算上述关联数组的长度counterArray

此处没有可用于计算关联数组对象长度的内置函数和属性。但是,我们可以通过其他方式计算关联数组对象的长度。除此之外,我们还可以Object通过向原型添加方法或属性来扩展,以便计算长度。但是,扩展对象可能会破坏各种库中的枚举,或者可能会产生跨浏览器问题,因此除非必要,否则不建议使用它。同样,我们可以通过各种方式计算长度。

Objectkeys可用于计算对象长度的方法:


We can also calculate the length of an object by iterating through an object and by counting the object's own property.  

```javascript
function getSize(object){
  var count = 0;
  for(key in object){
    // hasOwnProperty method check own property of object
    if(object.hasOwnProperty(key)) count++;
  }
  return count;
}
我们还可以length直接添加方法Object
Object.length = function(){
  	var count = 0;
  for(key in object){
    // hasOwnProperty method check own property of object
    if(object.hasOwnProperty(key)) count++;
  }
  return count;
}
//Get the size of any object using
console.log(Object.length(counterArray))

另外的方式:我们也可以使用Underscore(推荐,因为它的重量轻)来计算对象长度。

本文翻译自:点击访问

 

猜你喜欢

转载自blog.csdn.net/qq_37939251/article/details/83180814