js面试题(更新中...)

1.js类型及检测方式

JS内置类型

原始数据类型:基础类型存储在栈内存,被引用或拷贝时,会创建一个完全相等的变量;占据空间小、大小固定,属于被频繁使用数据,所以放入栈中存储。

基本数据类型:Undefined、Null、Boolean、Number、String、
Symbol(es6新增,表示独一无二的值)和BigInt(es10新增);

引用数据类型:引用类型存储在堆内存,存储的是地址,多个引用指向同一个地址,这里会涉及一个“共享”的概念;占据空间大、大小不固定。引用数据类型在栈中存储了指针,该指针指向堆中该实体的起始地址。当解释器寻找引用值时,会首先检索其在栈中的地址,取得地址后从堆中获得实体。

引用数据类型:object、Array、function、Date

数据类型检验

(1)typeof
typeof 对于原始类型来说,除了 null 都可以显示正确的类型

console.log(typeof 2);               // number
console.log(typeof true);            // boolean
console.log(typeof 'str');           // string
console.log(typeof []);              // object     []数组的数据类型在 typeof 中被解释为 object
console.log(typeof function(){});    // function
console.log(typeof {});              // object
console.log(typeof undefined);       // undefined
console.log(typeof null);            // object     null 的数据类型被 typeof 解释为 object
typeof 对于对象来说,除了函数都会显示 object,所以说 typeof 并不能
准确判断变量到底是什么类型,所以想判断一个对象的正确类型,这时候
可以考虑使用 instanceof

(2)instanceof
instanceof 可以正确的判断对象的类型,因为内部机制是通过判断对象的原型链中是不是能找到类型的 prototype

console.log(2 instanceof Number);                    // false
console.log(true instanceof Boolean);                // false 
console.log('str' instanceof String);                // false  
console.log([] instanceof Array);                    // true
console.log(function(){} instanceof Function);       // true
console.log({} instanceof Object);                   // true    

(3)constructor

console.log((2).constructor === Number); // true
console.log((true).constructor === Boolean); // true
console.log(('str').constructor === String); // true
console.log(([]).constructor === Array); // true
console.log((function() {}).constructor === Function); // true
console.log(({}).constructor === Object); // true
这里有一个坑,如果我创建一个对象,更改它的原型,constructor就会变得不可靠了

(4)Object.prototype.toString.call()

Object.prototype.toString({})       // "[object Object]"
Object.prototype.toString.call({})  // 同上结果,加上call也ok
Object.prototype.toString.call(1)    // "[object Number]"
Object.prototype.toString.call('1')  // "[object String]"
Object.prototype.toString.call(true)  // "[object Boolean]"
Object.prototype.toString.call(function(){})  // "[object Function]"
Object.prototype.toString.call(null)   //"[object Null]"
Object.prototype.toString.call(undefined) //"[object Undefined]"
Object.prototype.toString.call(/123/g)    //"[object RegExp]"
Object.prototype.toString.call(new Date()) //"[object Date]"
Object.prototype.toString.call([])       //"[object Array]"
Object.prototype.toString.call(document)  //"[object HTMLDocument]"
Object.prototype.toString.call(window)   //"[object Window]"

2.new 操作符的作用

1.在内存中创建一个新对象
2、这个新对象内部的[[Prototype]]指针被赋值为构造函数的 prototype 属性。
3、构造函数内部的 this 被赋值为这个新对象 (即 this 指向新对象)。
4、执行构造函数内部的代码 (给新对象添加属性)
5、如果构造函数返回非空对象,则返回该对象,否则,返回刚创建的新对象

3.谈谈this对象的理解

定义

函数的 this 关键字在 JavaScript 中的表现略有不同,此外,在严格模式和非严格模式之间也会有一些差别
在绝大多数情况下,函数的调用方式决定了 this 的值(运行时绑定)
this 关键字是函数运行时自动生成的一个内部对象,只能在函数内部使用,总指向调用它的对象
同时,this在函数执行过程中,this一旦被确定了,就不可以再更改

new绑定

通过构建函数new关键字生成一个实例对象,此时this指向这个实例对象

new过程遇到return一个对象,此时this指向为返回的对象
如果返回一个简单类型的时候,则this指向实例对象
注意的是null虽然也是对象,但是此时new仍然指向实例对象

显示修改

apply()、call()、bind()是函数的一个方法,作用是改变函数的调用对象。它的第一个参数就表示改变后的调用这个函数的对象。因此,这时this指的就是这第一个参数

隐式绑定

函数还可以作为某个对象的方法调用,这时this就指这个上级对象
此时this指向的是window,这里的大家需要记住,this永远指向的是最后调用它的对象,虽然fn是对象b的方法,但是fn赋值给j时候并没有执行,所以最终指向window

默认绑定

严格模式下,不能将全局对象用于默认绑定,this会绑定到undefined,只有函数运行在非严格模式下,默认绑定才能绑定到全局对象

4. 解释下什么是事件代理?应用场景?

定义

事件代理,俗地来讲,就是把一个元素响应事件(click、keydown…)的函数委托到另一个元素
前面讲到,事件流的都会经过三个阶段: 捕获阶段 -> 目标阶段 -> 冒泡阶段,而事件委托就是在冒泡阶段完成
事件委托,会把一个或者一组元素的事件委托到它的父层或者更外层元素上,真正绑定事件的是外层元素,而不是目标元素
当事件响应到目标元素上时,会通过事件冒泡机制从而触发它的外层元素的绑定事件上,然后在外层元素上去执行函数

总结

适合事件委托的事件有:click,mousedown,mouseup,keydown,keyup,keypress
从上面应用场景中,我们就可以看到使用事件委托存在两大优点:
减少整个页面所需的内存,提升整体性能
动态绑定,减少重复工作
但是使用事件委托也是存在局限性:
focus、blur这些事件没有事件冒泡机制,所以无法进行委托绑定事件
mousemove、mouseout这样的事件,虽然有事件冒泡,但是只能不断通过位置去计算定位,对性能消耗高,因此也是不适合于事件委托的
如果把所有事件都用事件代理,可能会出现事件误判,即本不该被触发的事件被绑定上了事件

5.说说JavaScript中的事件模型

事件模型:
原始事件模型(DOM0级)
标准事件模型(DOM2级)
IE事件模型(基本不用)

原始事件模型

事件绑定监听函数比较简单, 有两种方式:
html直接绑定

<input type="button" onclick="fun()">

通过JS代码绑定

var btn = document.getElementById('.btn');
btn.onclick = fun;
绑定速度快
只支持冒泡,不支持捕获
同一个类型的事件只能绑定一次

标准事件模型

在该事件模型中,一次事件共有三个过程:
事件捕获阶段:事件从document一直向下传播到目标元素, 依次检查经过的节点是否绑定了事件监听函数,如果有则执行
事件处理阶段:事件到达目标元素, 触发目标元素的监听函数
事件冒泡阶段:事件从目标元素冒泡到document, 依次检查经过的节点是否绑定了事件监听函数,如果有则执行

IE事件模型

事件处理阶段:事件到达目标元素, 触发目标元素的监听函数。
事件冒泡阶段:事件从目标元素冒泡到document, 依次检查经过的节点是否绑定了事件监听函数,如果有则执行

6.说说你对事件循环的理解

首先,JavaScript是一门单线程的语言,意味着同一时间内只能做一件事,但是这并不意味着单线程就是阻塞,而实现单线程非阻塞的方法就是事件循环
在JavaScript中,所有的任务都可以分为
同步任务:立即执行的任务,同步任务一般会直接进入到主线程中执行
异步任务:异步执行的任务,比如ajax网络请求,setTimeout定时函数等
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

筱闯~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值