20个必会的JavaScript面试题(小结)


Posted in Javascript onJuly 02, 2019

问题1:JavaScript 中 undefined 和 not defined 的区别

JavaScript 未声明变量直接使用会抛出异常:var name is not defined,如果没有处理异常,代码就停止运行了。 但是,使用typeof undeclared_variable并不会产生异常,会直接返回 undefined。

var x; // 声明 x
console.log(x); //output: undefined 

console.log(typeof y); //output: undefined 

console.log(z); // 抛出异常: ReferenceError: z is not defined

问题2:下面的代码输出什么?

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

正确的答案应该是 1undefined。

JavaScript中if语句求值其实使用eval函数,eval(function f(){}) 返回 function f(){} 也就是 true。

下面我们可以把代码改造下,变成其等效代码。

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

上面的代码输出其实就是 1undefined。为什么那?我们查看下 eval() 说明文档即可获得答案

该方法只接受原始字符串作为参数,如果 string 参数不是原始字符串,那么该方法将不作任何改变地返回。

恰恰 function f(){} 语句的返回值是 undefined,所以一切都说通了。

注意上面代码和以下代码不同。

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

问题3:在JavaScript中创建一个真正的private方法有什么缺点?

每一个对象都会创建一个private方法的方法,这样很耗费内存

观察下面代码

var Employee = function (name, company, salary) {
  this.name = name || "";    
  this.company = company || ""; 
  this.salary = salary || 5000; 

  // 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中什么是闭包?写出一个例子

老生常谈的问题了,闭包是在一个函数里声明了另外一个函数,并且这个函数访问了父函数作用域里的变量。

下面给出一个闭包例子,它访问了三个域的变量

  1. 它自己作用域的变量
  2. 父函数作用域的变量
  3. 全局作用域的变量
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 is closure that is defined inside outerFunc

输出很简单:

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 返回一个匿名函数,运行这个匿名函数又返回一个匿名函数,最里面的匿名函数可以访问 x,y,z 进而算出乘积返回即可。

对于JavaScript中的函数一般可以考察如下知识点:

  • 函数是一等公民
  • 函数可以有属性,并且能连接到它的构造方法
  • 函数可以像一个变量一样存在内存中
  • 函数可以当做参数传给其他函数
  • 函数可以返回其他函数

问题6:JavaScript怎么清空数组?

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

怎么清空 arrayList

方法1

arrayList = [];

直接改变arrayList所指向的对象,原对象并不改变。

方法2

arrayList.length = 0;

这种方法通过设置length=0 使原数组清除元素。

方法3

arrayList.splice(0, arrayList.length);

和方法2相似

问题7:怎么判断一个object是否是数组(array)?

方法1

使用 Object.prototype.toString 来判断是否是数组

function isArray(obj){
  return Object.prototype.toString.call( obj ) === '[object Array]';
}

这里使用call来使 toString 中 this 指向 obj。进而完成判断

方法二

使用 原型链 来完成判断

function isArray(obj){
  return obj.__proto__ === Array.prototype;
}

基本思想是利用 实例如果是某个构造函数构造出来的那么 它的 __proto__是指向构造函数的 prototype属性。

方法3

利用JQuery

function isArray(obj){
  return $.isArray(obj)
}

JQuery isArray 的实现其实就是方法1

问题8:下面代码输出什么?

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

输出是 0。 delete 操作符是将object的属性删去的操作。但是这里的 x 是并不是对象的属性, delete 操作符并不能作用。

问题9:下面代码输出什么?

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

console.log(output);

输出是 1。delete 操作符是将object的属性删去的操作。但是这里的 x 是并不是对象的属性, delete 操作符并不能作用。

问题10:下面代码输出什么?

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

console.log(output);

输出是 undefined。x虽然是全局变量,但是它是一个object。delete作用在x.foo上,成功的将x.foo删去。所以返回undefined

问题11:下面代码输出什么?

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

输出是 xyz,这里的 emp1 通过 prototype 继承了 Employee的 company。emp1自己并没有company属性。所以delete操作符的作用是无效的。

问题12:什么是 undefined x 1 ?

在chrome下执行如下代码,我们就可以看到undefined x 1的身影。

var trees = ["redwood","bay","cedar","oak","maple"];
delete trees[3];
console.log(trees);

当我们使用 delete 操作符删除一个数组中的元素,这个元素的位置就会变成一个占位符。打印出来就是undefined x 1。 注意如果我们使用trees[3] === 'undefined × 1'返回的是 false。因为它仅仅是一种打印表示,并不是值变为undefined x 1。

问题13:下面代码输出什么?

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

输出是5。因为delete操作符并不是影响数组的长度。

问题14:下面代码输出什么?

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

输出是

1
truexyz
2
1

下面给出一个加法操作表

  • Number + Number -> 加法
  • Boolean + Number -> 加法
  • Boolean + Boolean -> 加法
  • Number + String -> 连接
  • String + Boolean -> 连接
  • String + String -> 连接

问题15:下面代码输出什么?

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

输出是 undefined。js中赋值操作结合律是右至左的 ,即从最右边开始计算值赋值给左边的变量。

上面代码等价于

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

问题16:下面代码输出什么?

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

输出是抛出异常,bar is not defined。 如果想让代码正常运行,需要这样修改代码:

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

或者是

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

明确说明这个下问题

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的定义是在运行时。想系统说明这个问题,我们要引入变量提升的这一概念。

我们可以运行下如下代码看看结果。

console.log(foo)
console.log(bar)

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

输出为

undefined
function bar(){ 
  // Some code
};

为什么那?为什么 foo 打印出来是 undefined,而 bar打印出来却是函数?

JavaScript在执行时,会将变量提升。

所以上面代码JavaScript 引擎在实际执行时按这个顺序执行。

// foo bar的定义位置被提升
function bar(){ 
  // Some code
}; 
var foo;

console.log(foo)
console.log(bar)

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

原代码的输出合理解释了。

问题18:下面代码输出什么?

var salary = "1000$";

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

  var salary = "5000$";

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

输出是

Original salary was undefined
My New Salary 5000$

这题同样考察的是变量提升。等价于以下代码

var salary = "1000$";

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

   salary = "5000$";

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

问题19:什么是 instanceof 操作符?下面代码输出什么?

function foo(){ 
 return foo; 
}

console.log(new foo() instanceof foo);

instanceof操作符用来判断是否当前对象是特定类的对象。

function Animal(){
  //或者不写return语句
  return this;
}
var dog = new Animal();
dog instanceof Animal // Output : true

但是,这里的foo定义为

function foo(){ 
 return foo; 
}

所以

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

所以 new foo() instanceof foo 返回 false

问题20: 如果我们使用JavaScript的"关联数组",我们怎么计算"关联数组"的长度?

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

其实答案很简单,直接计算key的数量就可以了。

Object.keys(counterArray).length // Output 3

本文给出的面试题答案只是很多合理答案中的几个,可能会不全面,欢迎大家补充。

由于个人疏忽等原因,本文中难免会存在少量错误,欢迎大家批评指正。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
accesskey 提交
Jun 26 Javascript
js控制分页打印、打印分页示例
Feb 08 Javascript
JS获取子窗口中返回的数据实现方法
May 28 Javascript
jQuery插件 Jqplot图表实例
Jun 18 Javascript
JavaScript中双符号的运算详解
Mar 12 Javascript
整理关于Bootstrap表单的慕课笔记
Mar 29 Javascript
jQuery实现简单的计时器功能实例分析
Aug 29 jQuery
使用D3.js创建物流地图的示例代码
Jan 27 Javascript
最后说说Vue2 SSR 的 Cookies 问题
May 25 Javascript
AngularJS实现与后台服务器进行交互的示例讲解
Aug 13 Javascript
vue项目添加多页面配置的步骤详解
May 22 Javascript
javascript读取本地文件和目录方法详解
Aug 06 Javascript
微信小程序如何调用新闻接口实现列表循环
Jul 02 #Javascript
Angular.JS读取数据库数据调用完整实例
Jul 02 #Javascript
js实现for循环跳过undefined值示例
Jul 02 #Javascript
Vue的路由及路由钩子函数的实现
Jul 02 #Javascript
Node.js 实现远程桌面监控的方法步骤
Jul 02 #Javascript
使用vue中的混入mixin优化表单验证插件问题
Jul 02 #Javascript
vue history 模式打包部署在域名的二级目录的配置指南
Jul 02 #Javascript
You might like
迅雷下载《中学科技》怀旧期刊下载
2021/02/27 无线电
在PHP3中实现SESSION的功能(一)
2006/10/09 PHP
thinkPHP2.1自定义标签库的导入方法详解
2016/07/20 PHP
随机显示经典句子或诗歌的javascript脚本
2007/08/04 Javascript
js DataSet数据源处理代码
2010/03/29 Javascript
Tinymce+jQuery.Validation使用产生的BUG
2010/03/29 Javascript
javascript模版引擎-tmpl的bug修复与性能优化分析
2011/10/23 Javascript
js判断选择时间不能小于当前时间的示例代码
2013/09/24 Javascript
js类式继承的具体实现方法
2013/12/31 Javascript
Nodejs异步回调的优雅处理方法
2014/09/25 NodeJs
javascript中call apply 的应用场景
2015/04/16 Javascript
js检测判断日期大于多少天的方法
2015/05/04 Javascript
JS简单实现动画弹出层效果
2015/05/05 Javascript
JS上传图片预览插件制作(兼容到IE6)
2016/08/07 Javascript
详解Vue.js搭建路由报错 router.map is not a function
2017/06/27 Javascript
浅谈angular2路由预加载策略
2017/10/04 Javascript
解决vue build打包之后首页白屏的问题
2018/03/06 Javascript
深入理解Promise.all
2018/08/08 Javascript
vue2.0$nextTick监听数据渲染完成之后的回调函数方法
2018/09/11 Javascript
微信小程序换肤功能实现代码(思路详解)
2020/08/25 Javascript
[02:38]2018年度DOTA2最佳劣单位选手-完美盛典
2018/12/17 DOTA
Python面向对象编程中的类和对象学习教程
2015/03/30 Python
urllib和BeautifulSoup爬取维基百科的词条简单实例
2018/01/17 Python
Django框架视图函数设计示例
2019/07/29 Python
Python破解BiliBili滑块验证码的思路详解(完美避开人机识别)
2020/02/17 Python
pandas分批读取大数据集教程
2020/06/06 Python
Keras—embedding嵌入层的用法详解
2020/06/10 Python
Python类的继承super相关原理解析
2020/10/22 Python
localStorage、sessionStorage使用总结
2017/11/17 HTML / CSS
工厂厂长的职责
2013/12/12 职场文书
法学院方阵解说词
2014/01/29 职场文书
开会迟到检讨书
2014/02/03 职场文书
2014年五四青年节演讲比赛方案
2014/04/22 职场文书
诺贝尔奖获得者名言100句:句句启人心智,值永久收藏
2019/08/09 职场文书
nginx里的rewrite跳转的实现
2021/03/31 Servers
Python还能这么玩之用Python修改了班花的开机密码
2021/06/04 Python