1.typeof 对类型的判断

(function()  {
return typeof arguments;
}
)();

  答案:"Object"

  解释:arguments是一个伪数组,是JavaScript内置对象。

2.函数的声明

var f = function g(){
return 23;
};
typeof g();

  答案:会报错。Uncaught ReferenceError: g is not defined

  解释:因为在这里function g(){return 23;};只是作为一个带有名字函数表达式,不是函数的声明。函数实际上是绑定到变量f,不是g。如果想调用这个函数,应该通过f()进行调用。

3.delete方法

(function(x){
delete x;
return x;
})(1);

  答案:1

  解释:delete是用来删除对象中的某个属性的方法,并不能直接删除变量。

4.变量的声明和赋值

var y = 1, x = y = typeof x;
x;

  答案:"undefined"

  解释:解析这段代码时,会先进行变量声明的提升,即var y;var x; 然后真正执行代码的时候,y先是被赋值为1,然后x=y=typeof x可以进行一下拆分:

     因为x被声明还未被赋值,所以x为undefined,自然typeof x的结果为 "undefined"。=赋值是从右向左执行的,所以先是y = "undefined",再是x=y,

     理所当然,x的结果就是字符串类型的"undefined"。

5.自调用函数传函数参数

(function f(f){
return typeof f();
})(function(){ return 1; });

  答案:"number"

  解释:这段代码中是将函数function(){ return 1; }作为参数传给了自调用函数进行使用。对自调用函数内部return typeof f() ,f是传递过来的参数,先对它加了()进行函数调用,执行结果为1,;然后 typeof 1 的结果自然就是"number"了。

6.自调用函数和arguments对象

var foo = {
bar: function() {
return this.baz;
},
baz: 1
};
(function(){
return typeof arguments[0]();
})(foo.bar);

  答案:"undefined"

  解释:arguments是用来存放函数实参的伪数组对象。

     在执行自调用函数function(){return typeof arguments[0](); 的时候,argunments[0]()实际上就是(function() { return this.baz;})(),这就需要理解this的指向问题了,我们传参foo.bar时实际上是传递的foo对象中bar属性所对应的属性值,即只是函数体function() { return this.baz;},需要理解的就是这只是一个普通函数,其this的指向对应的是window,并不是foo。又因为window中并没有属性baz,执行结果自然是undefined,再通过typeof检测其类型,最终结果就是"undefined"。

     可以结合下面的代码进行理解,下面代码的结果也是"undefined"。

var foo = {
bar: function(){ return this.baz; },
baz: 1
}
f = foo.bar;
typeof f();

7.逗号操作符

var f = (
function f(){ return "1"; },
function g(){ return 2; }
)();
typeof f;

  答案:"number"

  解释:逗号操作符的使用可以很混淆,用下面这段代码说明它的行为:

var x = (1, 2, 3);
x;

  x的值是3,这表明,当有一系列的组合在一起,并由逗号分隔的表达式,它们从左到右进行计算,但只有最后一个表达式的结果保存。由于同样的原因,这个问题可以改写为减少混乱:

var f = (function g(){ return 2; })();
typeof f;

8.函数声明

var x = 1;
if (function f(){}) {
x += typeof f;
}
x;

  答案:"1undefined"

  解释:同第二题一样,if()括号中的只能算是函数表达式,并不是说函数的声明,所以,用typeof检测 f 时,结果为undefined

9.预解析

(function f(){
function f(){ return 1; }
return f();
function f(){ return 2; }
})();

  答案:2

  解释:在执行return之前,函数声明会在任何表达式被解析和求值之前先被解析和求值,即使你的声明在代码的最后一行,它也会在同作用域内第一个表达式之前被解析/求值。题目中函数提升了两次,第二次把第一次覆盖了。

10.创建对象,new关键字

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

  答案:false

  解释:值得注意的是 instanceof 检测的是原型。

     对于new关键字,做了几件事:1.创建空对象。2.让this指向当前对象。3.执行构造函数内部代码。4.默认如果没有覆盖这个空对象的话,返回this(当前对象)。

     我们在看 f() 返回了 return f;构造函数本身在 new 的过程中会返回一个表示该对象的实例。但是函数的返回值(这是返回的是构造函数本身)覆盖了这个实例,这个new 就形同虚设。

     如果f的形式为 function f(){return this}或function f(){}结果就应该是true了。

11.数组,typeof

var x = [typeof x, typeof y][1];
typeof typeof x;

  答案:"string"

  解释:这题目比较简单,注意下返回类型即可。x = [ , ][1];即 x = typeof y = ‘undefind’。然后再typeof typeof x必然就是"string"了。

12.对象

function(foo){
return typeof foo.bar;
})({ foo: { bar: 1 } });

  答案:"undefined"

  解释:这个特别有误导性,要仔细看,{ foo: { bar: 1 } }传给了函数作为实参,所以要想取到bar的值应该是 foo.foo.bar,实参的foo里面并没有一个叫做bar的属性,只有属性foo

13.函数作用域,new关键字

function setName(obj) {
  obj.name = 'zs'
  var obj = new Object()
  obj.name = 'ls'
}
var obj = new Object()
setName(obj)
console.log(obj.name)

  答案:'zs'

  解释:代码执行时从第6行开始看,先是创建了一个obj对象。

     在执行函数setName(obj)时,第2行处给这个对象新增了name属性,并赋值为‘zs’。

     执行到第3行处是,又新创建了一个名为obj的对象,因为对象的存储方式,所以两者并不冲突,也不指向同一个位置。这时候我们执行到第4行代码处是在给这个新对象添加属性并赋值为‘ls’,原始obj对象的属性值没有被修改。

     执行完函数后,又会继续执行第8行,这时候因为函数局部作用域的限制,只能访问到在函数外部定义的obj(第一个obj),所以输出的结果也就是‘zs’了。

     另外如果是下面这种情况,结果就是'ls'了

function setName(obj) {
obj.name = 'zs'
var obj = new Object()
obj.name = 'ls'
return obj
}
var obj = new Object()
obj = setName(obj)
console.log(obj.name)

14.闭包

var arr = [];
for(var i=0;i<3;i++) {
arr[i] = function() {
console.log(i)
}
}
arr[0]();
arr[1]();
arr[2]();

  答案:3  3  3

  解释:从上面的代码可以看到,在for循环遍历的过程中,只是给数组中存入了三个函数,该函数提供了在控制台中打印 i 的功能。而等到函数真正被调用执行时,i 的值早就已经变为了3,这时候再打印结果就只能全都是3了。

  另外,如果想要输出 1  2  3 的结果,就需要进行如下的函数闭包操作,即在遍历的时候就将 i 的值传递到函数内部在内存中存储起来,再调用的时候就可以输出1  2  3 了。

var arr = [];
for(var i=0;i<3;i++) {
arr[i] = (function(n) {
// 这个位置是闭包环境
return function() {
console.log(n)
}
})(i);
}
arr[0]();
arr[1]();
arr[2]();

js面试代码中的“坑”的更多相关文章

  1. java代码中的坑

    1.Integer 类型数值比较: public static void main(String[] args) {         // TODO Auto-generated method stu ...

  2. SpringMVC学习系列-后记 结合SpringMVC和Hibernate-validator,根据后台验证规则自动生成前台的js验证代码

    在SpringMVC学习系列(6) 之 数据验证中我们已经学习了如何结合Hibernate-validator进行后台的数据合法性验证,但是通常来说后台验证只是第二道保险,为了更好的用户体验会现在前端 ...

  3. 坑!vue.js在ios9中失效

    坑!vue.js在ios9中失效! 接到实现,在移动端生成一个分享链接,分享到微信,在微信中打开,加入! 好,用vue实现----------------------->写代码--------- ...

  4. Next.js 在 Serverless 中从踩坑到破茧重生

    作者 杨苏博,偏后端的全栈开发,目前负责腾云扣钉的 Cloud Studio 产品.在团队中负责接技术架构设计与 Review.Cloud Studio 编辑器内核设计与开发.部分核心插件设计与开发: ...

  5. Angularjs在控制器(controller.js)的js代码中使用过滤器($filter)格式化日期/时间实例

    Angularjs内置的过滤器(filter)为我们的数据信息格式化提供了比较强大的功能,比如:格式化时间,日期.格式化数字精度.语言本地化.格式化货币等等.但这些过滤器一般都是在VIEW中使用的,比 ...

  6. 用 highlight.js 为文章中的代码添加语法高亮

    来源:http://www.ghostchina.com/adding-syntax-highlighting-to-ghost-using-highlight-js/ --------------- ...

  7. 在Sublime Text 3 中安装SublimeLinter,Node.js进行JS&CSS代码校验

    转载自:http://www.wiibil.com/website/sublimelinter-jshint-csslint.html 在Sublime Text中安装SublimeLinter,No ...

  8. js代码中的闭包

    作为一个后台开发人员了解前端非常重要,尤其是深处学校实验室做项目时前端把写好的代码直接给你,然后你在修改的时候.我经常做的就是修改前端的代码的HTML和后台交互的部分以及js的ajax部分,之后修改之 ...

  9. jQuery Validate 表单验证插件----通过name属性来关联字段来验证,改变默认的提示信息,将校验规则写到 js 代码中

    一.下载依赖包 网盘下载:https://yunpan.cn/cryvgGGAQ3DSW  访问密码 f224 二. 添加一个另外一个插件jquery.validate.messages_cn.js. ...

随机推荐

  1. idea新建项目相关名词意义

    新建项目中的对比 建完之后的项目对比 对比 新建中Artifact的名称对应maven中名字 新建中package的名字对应的是项目中src下package名字 新建中project name的名字对 ...

  2. 《JavaScript高级程序设计》读书笔记(三)基本概念第四小节 操作符

    内容---语法 上一小节---数据类型 本小节 操作符---流程控制语句---理解函数 操作符--操作数据值的操作符--算术(如加减).位操作符.关系.相等--ECMAScript操作符可以适用于很多 ...

  3. ICCV2019 oral:Wavelet Domain Style Transfer for an Effective Perception-distortion Tradeoff in Single Image Super-Resolution

    引言 基于低分辨率的图像恢复高分辨图像具有重要意义,近年来,利用深度学习做单张图像超分辨主要有两个大方向:1.减小失真度(distortion, 意味着高PSNR)的图像超分辨,这类方法主要最小化均方 ...

  4. Python:列表类型

    概念 列表:有序的,可变的,元素集合 因为列表和字符串都是序列类型,所以很多操作和字符串很相似 但是注意:列表是可变类型,字符串是不可变类型 定义 基本定义 定义方法:[ 元素1, 元素2, .... ...

  5. POJ-2891 Strange Way to Express Integers(拓展中国剩余定理)

    放一个写的不错的博客:https://www.cnblogs.com/zwfymqz/p/8425731.html POJ好像不能用__int128. #include <iostream> ...

  6. SprintBoot学习(三)

    Thymeleaf模板引擎 1.thymeleaf是一个Java类库,,他是xml/xhtml/html5的模板引擎可以作为view层 2.themeleaf基本语法 引入thymeleaf < ...

  7. Spring学习(八)

    AOP的重要概念 1.切面 : 切点(Pointcut) + Advice[ 在哪里 .加什么 ] 2.Advice: 在 切点 选中的 连接点 "加入" 的 代码 就是 Advi ...

  8. 【译】高级T-SQL进阶系列 (二)【下篇】:使用 APPLY操作符

    [译注:此文为翻译,由于本人水平所限,疏漏在所难免,欢迎探讨指正] 原文链接:传送门. 使用OUTER APPLY 操作符 OUTER APPLY操作符工作起来和CROSS APPLY比较类似.唯一的 ...

  9. Android Studio中 安卓模拟器 联网

    方案一:之前做测试的时候发现虚拟机无法联网(浏览器打开 www.baidu.com, 显示 403 forbidden): 解决方案:关闭已经打开的虚拟机,进入到 SDK 安装目录下,按住 shift ...

  10. 关于java自学的内容以及感受(7.28)

    这一周学习了关于一些算法运算,我进行了程序的编写与运行,代码如下: public class TestSign{ public static void main(String[] args){ int ...