前端面试题总结之(三):JavaScript篇(陆续更新)

前言

你好,我是Dr.叶子,用心写最优美的博客,弹最好听的钢琴!

最近更新:

  • 2021年6月6日

1. JS的数据类型

  • 基本类型:
    String、Number、Boolean、Null、Undefined、Symbol

  • 引用类型:
    Object、Array、Function

注:Symbol 是 ES6 引入了一种新的原始数据类型,表示独一无二的值。


2. 判断JS数据类型的方法

  • typeof:
typeof "John"                 // 返回 "string"
typeof 3.14                   // 返回 "number"
typeof NaN                    // 返回 "number"
typeof false                  // 返回 "boolean"
typeof Symbol()				  // 返回 "symbol"
typeof myCar                  // 返回 "undefined" 
typeof function () {}         // 返回 "function"
typeof [1,2,3,4]              // 返回 "object"
typeof {name:'John', age:34}  // 返回 "object"
typeof null                   // 返回 "object" 
typeof new Date(),			  // 返回 "object" 
typeof new Number(100), 	  // 返回 "object" 
typeof new String('abc'),     // 返回 "string"
typeof new Boolean(true),     // 返回 "boolean"

返回小写字符串数据类型,包括以下 7 种:string、number、boolean、symbol、undefined、function 、object 等。

  • 基本类型:null 返回 “object” 外,一律返回对应类型。
  • 引用类型:function 返回 “function” 外,一律返回 “object” 类型。

 

  • instanceof: 原型检测
    表达式:A instanceof B
    如果 A 是 B 的实例,则返回 true,否则返回 false
// 返回 false
'abc' instanceof String, //false
123 instanceof Number, //false
false instanceof Boolean, //false
undefined instanceof Object, //false
null instanceof Object, //false
// 返回 true
[] instanceof Array, //true
function(){} instanceof Function, //true
{a:1,b:2,c:3} instanceof Object, //true
new Date() instanceof Date, //true

注意: instanceof 后面一定要是对象类型,首字母大写。

 

  • constructor: prototype原型对象上的属性,指向构造函数
function Person(){}
var p= new Person();
// 常见
"abc".constructor==String,					// 返回 true
(123).constructor==Number,					// 返回 true
true.constructor==Boolean,					// 返回 true
[].constructor==Array,						// 返回 true
{name:'tom', age:25}.constructor==Object,	// 返回 true
// 特殊
p.constructor==Person,						// 返回 true
Person.constructor==Function,				// 返回 true
new Date().constructor==Date,				// 返回 true
/^[a-zA-Z]{1,5}$/.constructor==RegExp,		// 返回 true
new Error().constructor==Error				// 返回 true

undefined 和 null 没有constructor属性。

 

  • Object.prototype.toString: 最准确的、最标准的数据类型判断方法
Object.prototype.toString.call('') ;   // [object String]
Object.prototype.toString.call(1) ;    // [object Number]
Object.prototype.toString.call(true) ; // [object Boolean]
Object.prototype.toString.call(Symbol()); //[object Symbol]
Object.prototype.toString.call(undefined) ; // [object Undefined]
Object.prototype.toString.call(null) ; // [object Null]
Object.prototype.toString.call(new Function()) ; // [object Function]
Object.prototype.toString.call(new Date()) ; // [object Date]
Object.prototype.toString.call([]) ; // [object Array]
Object.prototype.toString.call(new RegExp()) ; // [object RegExp]
Object.prototype.toString.call(new Error()) ; // [object Error]
Object.prototype.toString.call(document) ; // [object HTMLDocument]
Object.prototype.toString.call(window) ; //[object global] window 是全局对象 global 的引用

3. “ i++ ” 和 “ ++i ”的区别

  • “ i++ ” : 先引用 i 的值,而后递增 1;

  • “ ++i ” : 先递增 1,而后引用 i 的值;


4. JS原型对象 prototype

  • 使用 prototype 属性就可以给对象的构造函数添加新的属性:
// 构造器内定义属性
function Fun(a, b) {
  this.a = a;
  this.b = b;
}

// 原型属性定义方法
Fun.prototype.c = function() {
  return this.a + this.b;
}

// 定义属性
Fun.prototype.d = 1;
Fun.prototype.e = 2;


// 字面量定义方法,原型被重写,原有属性和方法被更新
Fun.prototype = {
  c : function() {
    return this.a + this.b;
  }
}

5. JS输入&输出

  • 输入
// 1.弹出警告框
alert("提示内容");

// 2.向文档流中打印输出(页面展示)
document.write("页面内容");

// 3.向控制台打印输出
console.log("控制台内容");
  • 输出
// 1.带输入框的弹框
prompt("标题","请输入...");

// 2.确认对话框
confirm("确认对话框");

// 3.表单中的输入框
<form>...</form>

6. JS闭包

  • 使得函数拥有私有变量变成可能。

例子1:

// 函数
function plusFunc() {
	// 局部变量
    var counter = 0;
    // 嵌套的函数
    function iterator() {
		return counter += 1;
	}
    return iterator
}
// 实例化
var add = plusFunc();

console.log(add());// 1
console.log(add());// 2
console.log(add());// 3

例子2:

// 函数
function makeAdder(x) {// 变量x
	// 返回嵌套的函数
	return function(y) {
		return x + y;
	};
}

// 实例化
var add5 = makeAdder(5);
var add10 = makeAdder(10);

console.log(add5(2));  // 7
console.log(add10(2)); // 12

闭包: 是一种保护私有变量的机制,在函数执行时形成私有的作用域,保护里面的私有变量不受外界干扰。直观的说就是形成一个不销毁的栈环境


7. 赋值、浅拷贝、深拷贝

在这里插入图片描述

  • 浅拷贝: 只复制指针,不复制对象本身,新旧对象共享同内存;
  • 深拷贝: 创建新对象,跟原对象不共享内存,修改新对象不影响原对象;

只针对 Object 和 Array 这样的复杂类型的;


8. 回流(Reflow)、重绘(Repaint)

  • 回流(重排):
  1. 对 DOM 的修改引发了几何尺寸的变化(修改元素的宽、高、位置、隐藏元素等);
  2. 浏览器将重新计算元素的几何属性(影响父、子、兄弟节点),然后再将计算的结果重新绘制出来。
  • 重绘:
  1. 对 DOM 的修改只引发了样式的变化、未影响其几何属性(修改元素的颜色或背景色等);
  2. 浏览器不需重新计算元素的几何属性、直接为该元素绘制新的样式。

9. 节流(throttle)、防抖(debounce)

  • 节流: 通过特定时间内执行一次函数,保证函数有规律地运行

高频率事件在 n 秒内只触发一次,n 秒内不再触发
例子:

  • 鼠标滚动事件,通过节流操作限制每50ms执行一次鼠标滚动事件。

应用:

  • 搜索框input事件,实时搜索(间隔一段时间就请求查询);
  • 股票数据实时变动等。

【代码实现】

function coloring () {
	let r = Math.floor( Math.random() * 255 );
	let g = Math.floor( Math.random() * 255 );
	let b = Math.floor( Math.random() * 255 );
	document.body.style.background = `rgb(${r}, ${g}, ${b})`;
}

function throttle (func, delay) {
	let timer;
	return function () {
		let context = this;
		let args = arguments;
		if (timer) {
			return;
		}
		timer = setTimeout(function () {
			func.apply(context, arguments);
			timer = null;
		}, delay);
	}
}

window.addEventListener('resize', throttle(coloring, 2000));

 

  • 防抖: 短时间内连续触发的事件,重新计时,只执行一次

高频率事件在 n 秒内只触发一次,如果再次被触发,则重新计时
例子:

  • 快速点击10次登录按钮(突发10次点击事件),通过防抖操作将其归组为一次点击事件。

应用:

  • 防止表单多次提交;
  • 页面滚动的统计、输入框连续输入次数的控制等。

【代码实现】

const button = document.querySelector('input');

function doing () {
	console.log('正在执行...')
}

function debounce (func, delay) {
	let timer;
	return function () {
		let context = this;
		let args = arguments;
		clearTimeout(timer);
		timer = setTimeout(function () {
			func.apply(context, arguments);
		}, delay);
	}
}

button.addEventListener('click', debounce(doing, 1000));

 

10. 虚拟节点(一次插入10万条数据不卡顿)

  • document.createDocumentFragment()

创建一个新的空白的文档片段

  • window.requestAnimationFrame()

告诉浏览器——你希望执行一个动画,并且要求浏览器在下次重绘之前调用指定的回调函数更新动画。该方法需要传入一个回调函数作为参数,该回调函数会在浏览器下一次重绘之前执行

// 插入10万条数据
const total = 100000;
// 每次插入20条
const once = 20;
// 插入总次数
const loopCount = Math.ceil(total/once)
// 渲染的次数
let countRender = 0;
// 创建插入的父节点
const ul = const ul = document.getElementById('ul');

// 添加数据的方法
function add () {
	// 创建虚拟节点
	const fragment = document.createDocumentFragment();
	for(let i = 0; i < once; i++) {
		const li = document.createElement('li');
		li.innerHTML = Math.floor(Math.random() * 100000);
		fragment.appendChild(li);
	}
	ul.appendChild(fragment);
	countRender++;
	loop();
}

function loop() {
	if(countRender < loopCount) {
		window.requestAnimationFrame(add);
	}
}


 

推荐阅读

【1】彻底讲明白浅拷贝与深拷贝 .
【2】闭包的理解 .
【3】知乎:「每日一题」JS 中的闭包是什么? .
【4】W3Cschool:JavaScript 对象定义.


 

系列文章

前端面试题总结之(一):HTML篇.

前端面试题总结之(二):CSS篇.

前端面试题总结之(三):JavaScript篇.

前端面试题总结之(四):Vue开发相关.

前端面试题总结之(五):综合知识点.


 

后语

  1. 原创内容,转载说明出处哦!
  2. 以上内容本人整理,亲测可行,如有任何问题,敬请指正,谢谢~~
  3. 点赞、收藏、也欢迎打赏,我弹钢琴你听呀~~哈哈!
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值