Loading [MathJax]/jax/input/TeX/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >JS温故知新

JS温故知新

作者头像
隔壁老陈
发布于 2023-02-22 00:51:13
发布于 2023-02-22 00:51:13
52100
代码可运行
举报
文章被收录于专栏:老陈笔记老陈笔记
运行总次数:0
代码可运行

# JS中的数据类型及区别

基本类型(值类型): Number(数字),String(字符串),Boolean(布尔),Symbol(符号), null(空),undefined(未定义)在内存中占据固定大小, 保存在栈内存中。

引用类型(复杂数据类型): Object(对象)Function(函数)。其他还有Array(数组)Date(日期)RegExp(正则表达式)、特殊的基本包装类型(String、Number、Boolean) 以及单体内置对象(Global、Math)等。 引用类型的值是对象,保存在堆内存中。 栈内存存储的是对象的变量标识符以及对象在堆内存中的存储地址。

# JS中的数据类型检测方案

# 1.typeof

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
console.log(typeof 1);               // number
console.log(typeof true);            // boolean
console.log(typeof 'mc');            // string
console.log(typeof Symbol)           // function
console.log(typeof function(){});    // function
console.log(typeof console.log());   // undefined
console.log(typeof []);              // object 
console.log(typeof {});              // object
console.log(typeof null);            // object
console.log(typeof undefined);       // undefined

优点:能够快速区分基本数据类型

缺点:不能将Object、Array和Null区分,都返回object

# 2.instanceof

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
console.log(1 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

优点:能够区分Array、Object和Function,适合用于判断自定义的类实例对象

缺点:Number,Boolean,String基本数据类型不能判断

# 3.Object.prototype.toString.call()

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
var toString = Object.prototype.toString;
console.log(toString.call(1));                      //[object Number]
console.log(toString.call(true));                   //[object Boolean]
console.log(toString.call('mc'));                   //[object String]
console.log(toString.call([]));                     //[object Array]
console.log(toString.call({}));                     //[object Object]
console.log(toString.call(function(){}));           //[object Function]
console.log(toString.call(undefined));              //[object Undefined]
console.log(toString.call(null));                   //[object Null]

优点:精准判断数据类型

缺点:写法繁琐不容易记,推荐进行封装后使用

# JS单线程

  JavaScript 是 单线程 语言,意味着只有单独的一个调用栈,同一时间只能处理一个任务或一段代码。 队列、堆、栈、事件循环构成了 js 的并发模型,事件循环 是 JavaScript 的执行机制。 为什么js是一门单线程语言呢?最初设计JS是用来在浏览器验证表单以及操控DOM元素, 为了避免同一时间对同一个DOM元素进行操作从而导致不可预知的问题,JavaScript从一诞生就是单线程。 既然是单线程也就意味着不存在异步,只能自上而下执行,如果代码阻塞只能一直等下去, 这样导致很差的用户体验,所以事件循环的出现让 js 拥有异步的能力。

# JS垃圾回收机制

  项目中,如果存在大量不被释放的内存(堆/栈/上下文),页面性能会变得很慢。当某些代码操作不能被合理释放,就会造成内存泄漏。我们尽可能减少使用闭包,因为它会消耗内存。

浏览器垃圾回收机制/内存回收机制:

浏览器的Javascript具有自动垃圾回收机制(GC:Garbage Collecation),垃圾收集器会定期(周期性)找出那些不在继续使用的变量,然后释放其内存。

标记清除:在js中,最常用的垃圾回收机制是标记清除:当变量进入执行环境时,被标记为“进入环境”,当变量离开执行环境时,会被标记为“离开环境”。垃圾回收器会销毁那些带标记的值并回收它们所占用的内存空间。 谷歌浏览器:“查找引用”,浏览器不定时去查找当前内存的引用,如果没有被占用了,浏览器会回收它;如果被占用,就不能回收。

优化手段:

1、内存优化

(1)堆内存:fn = null 【null:空指针对象】

(2)栈内存:把上下文中,被外部占用的堆的占用取消即可。

2、内存泄漏优化

  在 JS 中,常见的内存泄露主要有 4 种,全局变量、闭包、DOM 元素的引用、定时器

# 节流防抖

节流:事件触发后,规定时间内,事件处理函数不能再次被调用。也就是说在规定的时间内,函数只能被调用一次,且是最先被触发调用的那次。

防抖:多次触发事件,事件处理函数只能执行一次,并且是在触发操作结束时执行。也就是说,当一个事件被触发准备执行事件函数前,会等待一定的时间(这时间是码农自己去定义的,比如 1 秒),如果没有再次被触发,那么就执行,如果被触发了,那就本次作废,重新从新触发的时间开始计算,并再次等待 1 秒,直到能最终执行!

使用场景: 节流:滚动加载更多、搜索框搜的索联想功能、高频点击、表单重复提交等 防抖:搜索框搜索输入,并在输入完以后自动搜索、手机号,邮箱验证输入检测、窗口大小 resize 变化后,再重新渲染。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/**
 * 节流函数 一个函数执行一次后,只有大于设定的执行周期才会执行第二次。有个需要频繁触发的函数,出于优化性能的角度,在规定时间内,只让函数触发的第一次生效,后面的不生效。
 * @param fn要被节流的函数
 * @param delay规定的时间
 */
function throttle(fn, delay) {
    //记录上一次函数触发的时间
    var lastTime = 0;
    return function(){
        //记录当前函数触发的时间
        var nowTime = Date.now();
        if(nowTime - lastTime > delay){
            //修正this指向问题
            fn.call(this);
            //同步执行结束时间
            lastTime = nowTime;
        }
    }
}

document.onscroll = throttle(function () {
    console.log('scllor事件被触发了' + Date.now());
}, 200); 

/**
 * 防抖函数  一个需要频繁触发的函数,在规定时间内,只让最后一次生效,前面的不生效
 * @param fn要被节流的函数
 * @param delay规定的时间
 */
function debounce(fn, delay) {
    //记录上一次的延时器
    var timer = null;
    return function () {
       //清除上一次的演示器
        clearTimeout(timer);
        //重新设置新的延时器
        timer = setTimeout(()=>{
            //修正this指向问题
            fn.apply(this);
        }, delay); 
    }
}
document.getElementById('btn').onclick = debounce(function () {
    console.log('按钮被点击了' + Date.now());
}, 1000);

# 作用域和闭包

  • 作用域 指代码当前上下文,控制着变量和函数的可见性和生命周期。最大的作用是隔离变量,不同作用域下同名变量不会冲突。
  • 作用域链 指如果在当前作用域中没有查到值,就会向上级作用域查询,直到全局作用域,这样一个查找过程所形成的链条就被称之为作用域链。 作用域可以堆叠成层次结构,子作用域可以访问父作用域,反之则不行。
  • 作用域具体可细分为四种:全局作用域、模块作用域、函数作用域、块级作用域

全局作用域: 代码在程序的任何地方都能被访问,例如 window 对象。但全局变量会污染全局命名空间,容易引起命名冲突。

模块作用域: 早期 js 语法中没有模块的定义,因为最初的脚本小而简单。后来随着脚本越来越复杂,就出现了模块化方案(AMD、CommonJS、UMD、ES6模块等)。通常一个模块就是一个文件或者一段脚本,而这个模块拥有自己独立的作用域。

函数作用域: 顾名思义由函数创建的作用域;闭包就是在该作用域下产生。

块级作用域: 由于 js 变量提升存在变量覆盖、变量污染等设计缺陷,所以 ES6 引入了块级作用域关键字来解决这些问题。典型的案例就是 let 的 for 循环和 var 的 for 循环。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// var demo
for(var i=0; i<10; i++) {
console.log(i);
}
console.log(i); // 10

// let demo
for(let i=0; i<10; i++) {
console.log(i);
}
console.log(i); //ReferenceError:i is not defined
  • 闭包: 函数A里包含了函数B,而函数B使用了函数A的变量,那么函数B被称为闭包或者闭包就是能够读取函数A内部变量的函数。 可以看出闭包是函数作用域下的产物,闭包会随着外层函数的执行而被同时创建,它是一个函数以及其捆绑的周边环境状态的引用的组合。换而言之,闭包是内层函数对外层函数变量的不释放。

闭包的特征

1、函数中存在函数; 2、内部函数可以访问外层函数的作用域; 3、参数和变量不会被 GC,始终驻留在内存中; 4、有内存地方才有闭包。

  所以使用闭包会消耗内存、不正当使用会造成内存溢出的问题,在退出函数之前,需要将不使用的局部变量全部删除。如果不是某些特定需求,在函数中创建函数是不明智的,闭包在处理速度和内存消耗方面对脚本性能具有负面影响。

常见的闭包应用场景

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// demo1 输出 3 3 3
for(var i = 0; i < 3; i++) {
setTimeout(function() {
console.log(i);
}, 1000);
}
// demo2 输出 0 1 2
for(let i = 0; i < 3; i++) {
setTimeout(function() {
console.log(i);
}, 1000);
}
// demo3 输出 0 1 2
for(let i = 0; i < 3; i++) {
(function(i){
setTimeout(function() {
console.log(i);
}, 1000);
})(i)
}

# 原型与原型链

原型关系

  • 每个 class都有显示原型 prototype
  • 每个实例都有隐式原型 _ proto_
  • 实例的_ proto_指向对应 class 的 prototype

原型: 在 JS 中,每当定义一个对象(函数也是对象)时,对象中都会包含一些预定义的属性。其中每个函数对象都有一个prototype 属性,这个属性指向函数的原型对象。

原型链:函数的原型链对象constructor默认指向函数本身,原型对象除了有原型属性外,为了实现继承,还有一个原型链指针__proto__,该指针是指向上一层的原型对象,而上一层的原型对象的结构依然类似。因此可以利用__proto__一直指向Object的原型对象上,而Object原型对象用Object.prototype.__ proto__ = null表示原型链顶端。如此形成了js的原型链继承。

特点: JavaScript对象是通过引用来传递的,我们创建的每个新对象实体中并没有一份属于自己的原型副本。当我们修改原型时,与之相关的对象也会继承这一改变。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2023-02-010,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
前端面试之JavaScript
基本类型(值类型): Number(数字),String(字符串),Boolean(布尔),Symbol(符号),null(空),undefined(未定义)在内存中占据固定大小,保存在栈内存中
CODER-V
2023/03/04
7850
前端面试之JavaScript
JS高级部分
函数对象和数组对象都属于Object对象,Object对象是一个大的范围,而后两者是一个两种特别的对象
大忽悠爱学习
2021/11/15
1K0
夯实JavaScript知识点一文足矣
引用类型包括对象object、数组array、函数function等,统称对象类型:
挨踢小子部落阁
2019/08/23
5470
夯实JavaScript知识点一文足矣
2022高频前端面试题合集之JavaScript篇(上)
解析:该题主要考察就是对 js 中的继承是否了解,以及常见的继承的形式有哪些。最常用的继承就是「组合继承」(伪经典继承)和圣杯模式继承。下面附上 js 中这两种继承模式的详细解析。
程序员法医
2022/12/20
1.2K0
2022高频前端面试题合集之JavaScript篇(上)
(建议收藏)原生JS灵魂之问, 请问你能接得住几个?(上)
笔者最近在对原生JS的知识做系统梳理,因为我觉得JS作为前端工程师的根本技术,学再多遍都不为过。打算来做一个系列,一共分三次发,以一系列的问题为驱动,当然也会有追问和扩展,内容系统且完整,对初中级选手会有很好的提升,高级选手也会得到复习和巩固。敬请大家关注!
桃翁
2019/11/05
1.6K0
(建议收藏)原生JS灵魂之问, 请问你能接得住几个?(上)
前端知识点总结js篇(中)
(总结不够全面,建议参考es6.ruanyifeng.com/#docs/promi…
zhouzhouya
2023/10/26
2630
前端知识点总结js篇(中)
面了十多家,总结出20道JavaScript 必考的面试题!
面临毕业季,相信有很多朋友正在进行找工作,背面试题;今天就分享给大家20道JavaScript必会的问题
程序员老鱼
2023/09/07
2290
面了十多家,总结出20道JavaScript 必考的面试题!
javascript 基础_JavaScript高级编程
1.分类: -基本类型 -String:任意字符串 -Number:任意的数字 -boolean: true/false -undefined:未定义 -null:空
全栈程序员站长
2022/09/24
1.6K0
javascript 基础_JavaScript高级编程
js面试题及答案2020_JS面试题大全
number、string、bootlean、null、undefined、Bigint 、Symbol
全栈程序员站长
2022/09/27
3850
JS学习笔记
内部函数被返回到外部,函数本身保留了父函数的AO,即使父元素执行完了,取消对AO的引用,但依旧被子函数保留下来了,就形成了闭包。
小丞同学
2021/08/16
4190
横扫 JS 面试核心考点
Javascript是前端面试的重点,本文重点梳理下Javascript中的常考知识点,然后就一些容易出现的题目进行解析。限于文章的篇幅,无法将知识点讲解的面面俱到,因此只罗列了一些重难点。
grain先森
2019/04/18
1.5K0
横扫 JS 面试核心考点
【JavaScript】 进阶教程 施工中~
每个函数都有一个prototype属性。它默认指向一个Object空对象(即成为:原型对象)
杨丝儿
2022/02/24
1.4K0
【JavaScript】 进阶教程 施工中~
daily-question-02(前端每日一题02)
在这里记录着每天自己遇到的一道印象深刻的前端问题,以及一道生活中随处可见的小问题。
小皮咖
2019/11/05
4860
2021JavaScript面试题(最新)不定时更新(2021.11.6更新)
js 一共有六种基本数据类型,分别是 Undefined、Null、Boolean、Number、String,还有在 ES6 中新增的 Symbol 类型。 Symbol 代表创建后独一无二且不可变的数据类型,它的出现我认为主要是为了解决可能出现的全局变量冲突的问题。
全栈程序员站长
2022/09/07
2.6K0
利用这 66 条 JS 知识抓住年底最后一次跳槽涨薪的机会
作者: Jake Zhang https://juejin.cn/post/6844904200917221389
用户4456933
2021/06/01
7140
利用这 66 条 JS 知识抓住年底最后一次跳槽涨薪的机会
前端面试指南之JS面试题总结
根据 JavaScript 中的变量类型传递方式,分为基本数据类型和引用数据类型两大类七种。
loveX001
2022/10/10
8640
由浅入深,66条JavaScript面试知识点
作者:Jake Zhang https://juejin.cn/post/6844904200917221389
用户4456933
2021/06/01
7400
由浅入深,66条JavaScript面试知识点
JavaScript(高级)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
神葳
2021/01/22
9140
由浅入深,66条JavaScript面试知识点
来源:https://juejin.im/post/5ef8377f6fb9a07e693a6061
zz_jesse
2020/07/07
1K0
由浅入深,66条JavaScript面试知识点
jQuery源码浅析
如果说php是世界上最好的语言,那么javascript无疑可以称为世界上最飘逸的语言,最近看了下jQuery的源码,实现了一个简陋的jQuery。我觉得要看懂jQuery整体结构,需要搞懂js作用域链,闭包,js prototype继承,关于闭包网络上的定义实在太多了,这里参照了js权威指南里的定义,感觉从js的角度好理解一点。
用户3094376
2018/09/12
9690
相关推荐
前端面试之JavaScript
更多 >
LV.0
这个人很懒,什么都没有留下~
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验