1.数据类型

  • number:数字类型
  • string:字符串类型
  • boolean:布尔值类型
  • undefined:未定义类型
  • null:空值类型
  • object:对象类型
  • symbol:symbol类型
  • bigint:大数字类型

2.闭包

可以读取其他函数内部变量的函数。

缺点:容易内存泄漏

优点:外部可以访问局部

3. 原型 原型链

  • prototype: 显式原型
  • __ proto__: 隐式原型
//首先两个类并实例化
class Person{
	constructor(value) {
		this.value = value
	}
	teach(a){
		console.log('你好,调用了Person类teach方法',a)
	}
}
//继承类Person

class PersonF extends Person{
	constructor(value) {
		super(value)
	}
	son(a){
		console.log('你好,调用了PersonF类son方法',a)
	}
}
let Person0 = new Person('小明')
let PersonF1 = new PersonF('小红')
//此时分配了四块内存如图所示

我们接下来看看什么是原型 什么是原型链

PersonF1.teach(‘调用成功’)

这个是继承类的实例对象调用被继承类中的方法 在这个原型链上进行调用多个过程

console.log(typeof Person,typeof Person0)
// 这是使用了了四个内存
console.log(Person === PersonF)
console.log(Person === Person0)
console.log(Person0 === PersonF1)
// 下面我们要通过 实例PersonF1调用teach方法 //prototype  __proto__
PersonF1.teach('调用成功')  //调用成功
console.log('对象PersonF1的隐性原型是否和PersonF的显性原型指向同一块地址',PersonF1.__proto__ === PersonF.prototype)
console.log('类PersonF的隐性原型是否和Person是同一块内存地址',PersonF.__proto__ === Person)
console.log('从Person上找到方法teach',Person.prototype.teach)
console.log('继承之后的方法是否又分配新的内存?(true标识没有)',Person.prototype.teach === PersonF.prototype.teach)
//所以看图
所以PersonF1调用类Person方法的过程就是。1.先寻找 PersonF1 ._proto_找到PersonF.prototype。2.找到PersonF.prototype._proto_。3.此时查找到Person的prototype 找到 方法并调用。

4.作用域 作用域链

5.变量提升 函数提升

通常JS引擎会在正式执行之前先进行一次预编译,在这个过程中,首先将变量声明及函数声明提升至当前作用域的顶端,然后进行接下来的处理

引擎是把函数声明整个地提升到了当前作用域的顶部

/* 
			变量提升
		 */
			console.log(namea) // undefined
			var namea = '找不到'
			
			if (false) {
			  var age = 23
			}
			console.log(age) // undefined 
			
		/* 
			函数提升
		 */
		console.log(fun) // function fun() {}
		function fun() {}
		
		if (false) {
		  function fun2(){}
		}
		console.log(fun2) // undefined 
		

6.isNaN 和 Number.isNaN

  • isNaN:除了判断NaN为true,还会把不能转成数字的判断为true,例如’xxx’
  • Number.isNaN:只有判断NaN时为true,其余情况都为false

7.遍历原型的属性(const key in object)

function Person(name) {
  this.name = name
}
Person.prototype.age = 23
const person = new Person('Sunshine_lin')
for (const key in person) { console.log(key) } // name age
// 使用 hasOwnProperty
for (const key in person) {
  person.hasOwnProperty(key) && console.log(key)
} // name

8.valueOf 与 toString

1、valueOf偏向于运算,toString偏向于显示

2、对象转换时,优先调用toString

3、强转字符串优先调用toString,强转数字优先调用valueOf

4、正常情况下,优先调用toString

5、运算操作符情况下优先调用valueOf

9.变量在内存中存在形式

  • 基本数据类型:存在栈内存
  • 引用数据类型:指针存栈内存,指向堆内存中一块地址,内容存在堆内存中
  • 也有说法说其实JavaScript所有数据都存堆内存中,我也比较赞同这种说法

10. null undefined

相同点

  • 都是空变量
  • 都是假值,转布尔值都是false
  • null == undefined 为 true

不同点

  • typeof判断null为object,判断undefined为undefined
  • null转数字为0,undefined转数字为NaN
  • null是一个对象未初始化,undefined是初始化了,但未定义赋值
  • null === undefined 为 false

11. 0.1 + 0.2 === 0.3,对吗?

不对,JavaScript的计算存在精度丢失问题

console.log(0.1 + 0.2 === 0.3) // false
复制代码
  • 原因:JavaScript中小数是浮点数,需转二进制进行运算,有些小数无法用二进制表示,所以只能取近似值,所以造成误差
  • 解决方法:
    • 先变成整数运算,然后再变回小数
    • toFixed() 性能不好,不推荐

12. 绑定点击的方式

  • xxx.onclick = function (){}
  • <xxx onclick=""></xxx>
  • xxx.addEventListener('click', function(){}, false)

13.函数声明 和 函数表达式

  • 函数声明:享受函数提升
  • 函数表达式:归类于变量声明,享受变量提升
  • 函数提升优先级 > 变量提升优先级
console.log(fun) // fun () {}
// 函数表达式
var fun = function(name) {}
// 函数声明
function fun () {}
console.log(fun) // fun (name) {}

14. JavaScript的事件流模型有哪些?

  • 事件冒泡:由最具体的元素接收,并往上传播
  • 事件捕获:由最不具体的元素接收,并往下传播
  • DOM事件流:事件捕获 -> 目标阶段 -> 事件冒泡

//代码描写事件冒泡

点击儿子 父亲也会运行他自己的onclick() 阻止冒泡避免发生

    <script type="text/javascript">
        var div1 = document.querySelector(".div0");
        var div2 = document.querySelector(".div1");
           div2.onclick = function(){console.log('儿子')};
           div1.onclick = function(){console.log('父亲')};//父亲

//阻止冒泡
function stopBubble(e) {
  if (e.stopPropagation) {
    e.stopPropagation()
  } else {
    window.event.cancelBubble = true;
  }
}

    </script>
    <style type="text/css">
        .div0{
            width: 200px;
            height: 200px;
            background-color: antiquewhite;
        }
        .div1{
            width: 100px;
            height: 100px;
            background-color: aqua;
        }
    </style>

15.Ajax、Axios、Fetch

  • Ajax:是对XMLHttpRequest对象(XHR)的封装
  • Axios:是基于Promise对XHR对象的封装
  • Fetch:是window的一个方法,也是基于Promise,但是与XHR无关,不支持IE

16.load、$(document).ready、DOMContentLoaded的区别?

DOM文档加载的步骤为:

  • 1、解析HTML结构。
  • 2、加载外部脚本和样式表文件。
  • 3、解析并执行脚本代码。
  • 4、DOM树构建完成。// DOMContentLoaded触发、$(document).ready触发
  • 5、加载图片等外部文件。
  • 6、页面加载完毕。// load触发

17.事件委托(性能大幅度优化)

当所有子元素都需要绑定相同的事件的时候,可以把事件绑定在父元素上,这就是事件委托

  • 绑定在父元素上只需要绑定一次,节省性能
  • 子元素不需要每个都去绑定同一事件
  • 如果后续又有新的子元素添加,会由于事件委托的原因,自动接收到父元素的事件监听

//代码展示

当前有四(或者n)个选项 点击将触发事件 如果传统写法

window.onload = function(){
    var oUl = document.getElementById("ul1");
    var aLi = oUl.getElementsByTagName('li');
    for(var i=0;i<aLi.length;i++){
        aLi[i].onclick = function(){
            alert(123);
        }
    }
}

//加上冒泡 性能损耗巨大

//采用事件委托
//点击父节点触发获取鼠标点击元素 来触发函数 逻辑 性能 提高代码更加简洁
<div class="oBox">
			<li id="s1" class="s0">这是1</li>
			<li id="s2" class="s0">这是2</li>
			<li id="s3" class="s0">这是3</li>
		</div>
		<script type="text/javascript">
			let bb = document.querySelector('.oBox')
			bb.onclick = function (ev) {
				ev = ev || window.event //点击事件 获取元素
				let nowClickDom = ev.target //获取到 dom节点 点击的
				console.log(nowClickDom)
			}
 		</script>

18.数组去重

// 使用 Map 去重
function quchong1(arr) {
  const newArr = []
  arr.reduce((pre, next) => {
    if (!pre.get(next)) {
      pre.set(next, 1)
      newArr.push(next)
    }
    return pre
  }, new Map())
  return newArr
}

// 使用 Set 去重
function quchong (arr) {
    return [...new Set(arr)]
}

19. …用法

let a = { b : 1}
let c = a
let a = {b:1}
let c = a
//现在c和a指向相同 
//使用 ...
let d = {...a}
console.log(d)
a.b = 2
console.log(a,d)
//同理 数组[...arr]

20. set 数据结构

ES6 提供了新的数据结构 Set。它类似于数组,但是成员的值都是唯一的,没有重复的值。

(查看阮一峰老师详解)https://es6.ruanyifeng.com/#docs/set-map

遍历:

  • Set.prototype.keys():返回键名的遍历器
  • Set.prototype.values():返回键值的遍历器
  • Set.prototype.entries():返回键值对的遍历器
  • Set.prototype.forEach():使用回调函数遍历每个成员

21.map数据结构

JavaScript 的对象(Object),本质上是键值对的集合(Hash 结构),但是传统上只能用字符串当作键。这给它的使用带来了很大的限制。为了解决这个问题,ES6 提供了 Map 数据结构。它类似于对象,也是键值对的集合,但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键。也就是说,Object 结构提供了“字符串—值”的对应,Map 结构提供了“值—值”的对应,是一种更完善的 Hash 结构实现。如果你需要“键值对”的数据结构,Map 比 Object 更合适。

const m = new Map();
const o = {p: 'Hello World'};

m.set(o, 'content')
m.get(o) // "content"

m.has(o) // true
m.delete(o) // true
m.has(o) // false


(查看阮一峰老师详解)https://es6.ruanyifeng.com/#docs/set-map

22.继承

1.原型链继承

2.构造继承

3.实例继承

4.拷贝继承

5.组合继承

6.寄生组合继承

23. this指向

24.数组常用方法

25.Math的常用方法

26.内存泄漏

27.垃圾回收

28.BOM操作

本文内容参考文章(

作者:Sunshine_Lin
链接:https://juejin.cn/post/7020940475133591566
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

作者 译文

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注