JS进阶篇(前端面试题整合)(三)

简介: JS进阶篇(前端面试题整合)(三)

最近刷面试题遇到了一些比较有意思的题目,做个记录(题目均来源于牛客网,解析均是本人的理解,有任何问题欢迎在评论区指出)

Q1:请问以下两次检测对象constructor是否拥有属性名1的结果分别是什么?

1 in Object(1.0).constructor;
Number[1] = 123;
1 in Object(1.0).constructor;

A:false、true

解析:

首先可以认识一下 "in" :用于检查对象(数组)及其原型链中是否含有某键值,如

const arr = [0,2]
1 in arr // true

这里表示的是arr这个数组中存在 1 这个键值,即arr[1]

回归正题:Object(1.0) 相当于 new Number(1.0) ,new Number(1.0).constructor就拿到了Number构造函数,此时Number上还没有 1 这个属性,所以使用 in 返回false,而下一步中增加了这个属性,所以返回true

Q2:下面这段程序的显示结果是?

var x = new Boolean(false);
if (x) {
  alert('hi'); 
}
var y = Boolean(0);
if (y) {
  alert('hello');  
}

A:hi

解析:

Boolean(0)返回一个布尔类型的false
而new Boolean(false)返回一个布尔对象

Q3:以下哪些对象是Javascript内置的可迭代对象?

Array Map String Object

A:Array Map String

解析:

ES6中对可迭代的定义:一种数据结构存在Symbol.iterator属性,就表示可迭代
阮一峰的博客中还提到了以下可迭代的数据类型

  • Array
  • Map
  • Set
  • String
  • TypedArray
  • 函数的 arguments 对象
  • NodeList 对象

Q4:以下代码执行后,输出结果为

let x = 10;
let foo = () => {
    console.log(x);
    let x = 20;
    x++;
}
foo();

A:抛出ReferenceError

解析:使用let定义变量会形成 "暂时死区" 即foo作用域内获取的x就是等于20的那个,然而使用let去定义变量,变量不会得到提升,所以在定义前获取x会报错

Q5:请问以下JS代码会输出什么

var a = 10; 
(function a() {
    a = 20;
    console.log(a); 
})()

A:输出函数a的内容

解析: 立即执行函数中的a访问到的是函数a,当函数为IIFE的函数表达式时,与使用const类似(即无法修改这个值),与函数声明( function fun(){} )不相同,当执行a=20时,无法修改a的值

Q6:以下代码执行后,输出结果为

var a = 10;
function a(){}
console.log(typeof a)

A:输出 "number"

解析:我的理解是var会将声明提升到作用域的最高点,function会在js编译时加载在内存中
可以简单理解为:函数声明大于变量声明大于变量赋值,所以原式转换成了下面这段代码

function a(){}
var a;
a = 10;
console.log(typeof a)

验证方式:

console.log(typeof a)// function
var a = 10;
console.log(typeof a)// number
function a(){}
console.log(typeof a)// number

Q7:以下JavaScript代码,在浏览器中运行的结果是

var foo = {n:1};
(function(foo){
    console.log(foo.n);
    foo.n = 3;
    var foo = {n:2};
    console.log(foo.n);
})(foo);
console.log(foo.n);

A:1  2  3

解析:根据var的变量提升,可以得到以下代码;

var foo = {n:1};
(function(foo){
    var foo = foo // 这一步是参数(形参)的声明,赋值
    var foo // 此操作优先级没有参数高,所以不生效
    console.log(foo.n);// 此时foo指代参数,n为1
    foo.n = 3; // 参数引用了全局的foo,所以全局的foo此时已经是3了
    foo = {n:2}; // 给参数重新赋值,相当于指向了一块新内存
    console.log(foo.n); // 打印新内存的值:2
})(foo);
console.log(foo.n);

Q8:请问以下JS代码的输出结果以及变量i的值是?

var i = 100;
function foo() {
    bbb: try {
        console.log("position1");
        return i++;  }
    finally {
        break bbb;
    }
    console.log("position2");
    return i;
}
foo();

A:position1、position2、101

解析:在try中执行return不会打断finally的执行,但是没有打断i++执行,因此执行完try中的语句后,通过break bbb跳出到foo中的bbb级代码块,继续打印下面的position2

Q9:请问以下JS代码输出的结果是什么?

let obj = {
  num1: 117
}
let res = obj;// -----------1
obj.child = obj = { num2: 935 };// -----------2
var x = y = res.child.num2;// ----------3
console.log(obj.child);
console.log(res.num1);
console.log(y);

A:undefined、117、935

解析:这道题主要考察两点:

1.引用类型赋值

2.连续赋值机制

下面我对1-3步做一个分析:

第1步在栈中新建res变量使其引用地址指向obj,即与其共用一个堆地址(这一步可以看做是题目中对第二步的一个伏笔);

第2步是一个连续复制,赋值从右往左看,理解为以下代码,因为在赋值时obj指向了新的堆地址,obj.child中的obj已经不是赋值后的obj了,可以把它暂时看作是res

obj = { num2: 935 };
res.child = obj;

那么此时 res 就是{ child: {num2: 935}, num1: 117 },obj 就是{ num2: 935 };

第3步,连续复制,理解为以下代码

window.y = res.child.num2;
var x = window.y

此时res.child.num2是935,所以x和y都是935

Q10:在浏览器控制台中执行以下代码,输出的结果是

function test() {
    var n = 4399;
    function add(){
        n++;
        console.log(n);
    }
    return {n:n,add:add}
}
var result = test();// ------1
var result2 = test();// ------2
result.add();// ------3
result.add();// ------4
console.log(result.n);// ------5
result2.add();// ------6

A:4400 4401 4399 4400

解析:这道题考察闭包和函数作用域,首先咱得理解的是通过步骤1和2,产生的result和result2是两个不同对象(两个对象指向的堆地址不是一个,虽然内容一样),其次要了解的是test函数和add函数之间产生了闭包关系,所以执行3和4步骤后,n发生了变化,然而值得注意的是,此时的result.n却没有发生变化,这是因为在test函数作用域中,n作为一个基本类型的值随着函数执行完后随着return返回出来了,此时在add中修改的n与result.n已没有关联了。为了更好理解上述说法,我修改了代码,得出以下代码:

function test() {
    var n = {num:4399};
    function add(){
        n.num++;
        console.log(n);
    }
    return {n:n,add:add}
}
var result = test();
var result2 = test();
result.add() // {num: 4400}
result.add() // {num: 4401}
console.log(result.n) // {num: 4401}

这样写应该会有助于理解

言归正传,执行第5步时就是打印最早传入的n(4399),第六步由于上面解析中提到的步骤1和2,产生的result和result2是两个不同对象,所以,可以理解为result2也来了一次步骤3

相关文章
|
JSON 自然语言处理 前端开发
【01】对APP进行语言包功能开发-APP自动识别地区ip后分配对应的语言功能复杂吗?-成熟app项目语言包功能定制开发-前端以uniapp-基于vue.js后端以laravel基于php为例项目实战-优雅草卓伊凡
【01】对APP进行语言包功能开发-APP自动识别地区ip后分配对应的语言功能复杂吗?-成熟app项目语言包功能定制开发-前端以uniapp-基于vue.js后端以laravel基于php为例项目实战-优雅草卓伊凡
655 72
【01】对APP进行语言包功能开发-APP自动识别地区ip后分配对应的语言功能复杂吗?-成熟app项目语言包功能定制开发-前端以uniapp-基于vue.js后端以laravel基于php为例项目实战-优雅草卓伊凡
|
11月前
|
JavaScript 前端开发 API
|
11月前
|
前端开发 JavaScript 数据可视化
58K star!这个让网页动起来的JS库,前端工程师直呼真香!
Anime.js 是一款轻量级但功能强大的JavaScript动画引擎,它能够以最简单的方式为网页元素添加令人惊艳的动效。这个项目在GitHub上已经获得58,000+星标,被广泛应用于电商页面、数据可视化、游戏开发等场景。
426 8
|
自然语言处理 JavaScript 前端开发
当面试官再问我JS闭包时,我能答出来的都在这里了。
闭包(Closure)是前端面试中的高频考点,广泛应用于函数式编程中。它不仅指函数内部定义的函数,还涉及内存管理、作用域链和垃圾回收机制。闭包可以让函数访问其外部作用域的变量,但也可能引发内存泄漏等问题。通过合理使用闭包,可以实现模块化、高阶函数和回调函数等应用场景。然而,滥用闭包可能导致代码复杂度增加、调试困难以及潜在的性能问题。为了避免这些问题,开发时应谨慎处理闭包,避免不必要的嵌套,并及时清理不再使用的变量和监听器。
527 16
当面试官再问我JS闭包时,我能答出来的都在这里了。
|
资源调度 JavaScript 前端开发
前端开发必备!Node.js 18.x LTS保姆级安装教程(附国内镜像源配置)
本文详细介绍了Node.js的安装与配置流程,涵盖环境准备、版本选择(推荐LTS版v18.x)、安装步骤(路径设置、组件选择)、环境验证(命令测试、镜像加速)及常见问题解决方法。同时推荐开发工具链,如VS Code、Yarn等,并提供常用全局包安装指南,帮助开发者快速搭建高效稳定的JavaScript开发环境。内容基于官方正版软件,确保合规性与安全性。
12289 23
|
前端开发
【2025优雅草开源计划进行中01】-针对web前端开发初学者使用-优雅草科技官网-纯静态页面html+css+JavaScript可直接下载使用-开源-首页为优雅草吴银满工程师原创-优雅草卓伊凡发布
【2025优雅草开源计划进行中01】-针对web前端开发初学者使用-优雅草科技官网-纯静态页面html+css+JavaScript可直接下载使用-开源-首页为优雅草吴银满工程师原创-优雅草卓伊凡发布
427 1
【2025优雅草开源计划进行中01】-针对web前端开发初学者使用-优雅草科技官网-纯静态页面html+css+JavaScript可直接下载使用-开源-首页为优雅草吴银满工程师原创-优雅草卓伊凡发布
|
JavaScript 前端开发 Java
springboot解决js前端跨域问题,javascript跨域问题解决
本文介绍了如何在Spring Boot项目中编写Filter过滤器以处理跨域问题,并通过一个示例展示了使用JavaScript进行跨域请求的方法。首先,在Spring Boot应用中添加一个实现了`Filter`接口的类,设置响应头允许所有来源的跨域请求。接着,通过一个简单的HTML页面和jQuery发送AJAX请求到指定URL,验证跨域请求是否成功。文中还提供了请求成功的响应数据样例及请求效果截图。
294 3
springboot解决js前端跨域问题,javascript跨域问题解决
|
缓存 前端开发 JavaScript
JavaScript前端路由的实现原理及其在单页应用中的重要性,涵盖前端路由概念、基本原理、常见实现方式
本文深入解析了JavaScript前端路由的实现原理及其在单页应用中的重要性,涵盖前端路由概念、基本原理、常见实现方式(Hash路由和History路由)、优点及挑战,并通过实际案例分析,帮助开发者更好地理解和应用这一关键技术,提升用户体验。
652 1
|
存储 缓存 JavaScript
56 道高频 JavaScript 与 ES6+ 的面试题及答案(下)
56 道高频 JavaScript 与 ES6+ 的面试题及答案(下)
533 0
56 道高频 JavaScript 与 ES6+ 的面试题及答案(下)
|
存储 设计模式 缓存
14万字 | 400多道JavaScript 面试题及详细答案03(建议收藏)
14万字 | 400多道JavaScript 面试题及详细答案(建议收藏)
343 0
14万字 | 400多道JavaScript 面试题及详细答案03(建议收藏)