21个基本JavaScript面试问题
问题1
1. undefined
和not 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
返回,并且在运行时评估条件内的语句。undefined
if
if
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);
这里的每个实例变量emp1
,emp2
,emp3
有其自身的副本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 value
,array
和object
类型,我们就会有麻烦。
回到检查对象的类型,如前所述,我们可以使用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 1
JavaScript?
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 1
在铬和undefined
被放置在索引处。如果您在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.log
,salary
重新申报并分配5000$
。
问题20
instanceof
JavaScript中的运算符是什么?下面代码的输出是什么?
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
通过向原型添加方法或属性来扩展,以便计算长度。但是,扩展对象可能会破坏各种库中的枚举,或者可能会产生跨浏览器问题,因此除非必要,否则不建议使用它。同样,我们可以通过各种方式计算长度。
Object
有keys
可用于计算对象长度的方法:
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
(推荐,因为它的重量轻)来计算对象长度。
本文翻译自:点击访问