首页 > 其他分享 >前端 易混淆知识点梳理

前端 易混淆知识点梳理

时间:2024-11-17 18:19:43浏览次数:3  
标签:function 知识点 闭包 return log 混淆 console 解析 梳理

目录

一、严格模式与非严格模式

二、双等于三等的区别

三、防抖和节流

四、原型和原型链

五、页面重绘和回流

六、script标签async和defer

七、普通函数和箭头函数的区别

八、JS闭包

1、闭包特点

2、闭包作用

3、闭包风险

4、运用场景

1)常见闭包

2)实现模块化

3)缓存函数

4)封装私有变量

5)实现函数柯里化

7)防抖和节流


一、严格模式与非严格模式

在代码前加

"use strict"

或在class类里书写都会开启严格模式。

开启严格模式后,JS有以下变化:

变量

1、变量使用前必须声明 (此时,不声明就使用会直接报错)

2、不能直接用delete删除变量  (非严格模式的静默失败->严格模式的直接报错)

对象:

(非严格模式静默失败->严格模式的直接报错)(enumerable 不会报错)

1、对象的属性也不能直接使用delete来进行删除了

函数:

1、参数必须唯一   (非严格模式支持参数重复)

2、实参和形参不再具有映射关系  (非严格模式的arguments实参被修改,形参也会对应更改;在严格模式下,这两种参数一方被修改,另一方不会被一起更改)

3、不能使用argument的callee方法和caller

4、eval、agument类似这样的关键词名不得作为标识符,包括变量名、函数名等

5、不允许使用eval()、with()这两个方法  (这两个方法可能带来风险)

6、不允许出现八机制数  (因为八机制数开头是0会有歧义)

7、普通函数在全局里的this变成了undefined  (非严格模式时,普通函数在全局里的this指向window)

二、双等于三等的区别

1、“==”表示:equality -> 等同的意思,“==”两个等号使用时,若两边值的类型不同时,系统会先进行类型转换,再进行比较;

2、“==”表示:identity -> 恒等的意思,“===”三个等号使用时,系统不会进行类型转换,若类型不同,就表示一定不等的;

3. 简单说明使用三个等号(===)的判断规则:

(1)如果类型不同,就一定不相等

(2)如果两个都是数值,并且是同一个值,那么相等;如果其中至少一个是NaN,那么不相等。(判断一个值是否是NaN,只能使用isNaN( ) 来判断)

(3)如果两个都是字符串,每个位置的字符都一样,那么相等,否则不相等。

(4)如果两个值都是true,或是false,那么相等

(5)如果两个值都引用同一个对象或是函数,那么相等,否则不相等

(6)如果两个值都是null,或是undefined,那么相等

4. 简单说明使用两个等号(==)的判断规则:

(1)如果两个值类型相同,再进行三个等号(===)的比较

(2)如果两个值类型不同,也有可能相等,需根据以下规则进行类型转换在比较:

1)如果一个是null,一个是undefined,那么相等

2)如果一个是字符串,一个是数值,把字符串转换成数值之后再进行比较

3)另外两个NaN是不相等的。

三、防抖和节流

防抖:单位时间内,频繁触发事件,只执行最后一次

常见场景:输入框输入

若频繁监听可能会出现抖动情况,解决方案有二,一是在输入结束后再点击触发事件,而是通过防抖操作解决。利用定时器可以实现防抖的功能,每次触发先清掉以前的定时器。

节流:单位时间内,频繁触发事件,只触发一次

常见场景:高频事件、快速点击、鼠标滑动监听、resize事件、scroll事件

类比场景:火箭发射

代码实现:利用定时器,定时器执行完毕,再开启定时器(不要打断)

第三方库也可实现,lodash库,利用里面的debounce(防抖)和throttle(节流)来做。

代码实现,见文章最后部分,闭包的7里的代码。

四、原型和原型链

原型:

每个普通函数都有prototype属性,称为原型。因为这个属性的值是一个对象,所以也叫原型对象。

作用:

1、存放一些属性和方法,共享给实例对象使用

2、在JavaScript中实现继承

如:

    function Person(name, age) {
        this.name = name
        this.age = age
    }

    function Male() {

    }

    Male.prototype = new Person() //实现继承
    
    const man=new Male() 
    console.log(man)

__proto__:

每个对象都有__proto__属性

作用:

这个属性指向它的原型对象

原型链:

对象都有__proto__属性,这个属性指向它的原型对象,原型对象也是对象,也有__proto__属性。原型对象的__proto__指向原型对象的原型对象,这样一层层形成的链式结构称为原型链。最顶层Object的prototype的__proto__指向null, 到null结束。

常见场景:调用某个对象的方法,若在对象的最近一级有该方法就直接调用,若没有,就继续往上一级查找,找到后调用。

案例:

function Person() {
}
const person=new Person()
person.__proto__===Person.prototype   //true
person.__proto__.constructor===Person.prototype.constructor  //true
person.constructor===Person   //true
Person.prototype.constructor===person.constructor  //true

更多关于prototype见这篇:前端 JS面向对象 原型 prototype-CSDN博客

五、页面重绘和回流

重绘:

当元素的视觉效果发生变化,但几何属性(如位置和大小)没有改变时,浏览器会重新绘制元素。这包括改变元素的背景色、边框色、字体颜色等‌。

回流:

当元素的布局属性发生变化时,浏览器需要重新计算元素的位置和大小,并更新页面布局。这包括添加、删除或重新排列DOM节点,修改元素的尺寸、位置或样式等‌。

回流是一个相对昂贵的操作,因为它涉及到大量的计算和重新布局,频繁触发回流会导致性能问题,尤其是在处理复杂或大型的DOM结构时‌。

何时引起重绘?

1、视觉属性变化时:如颜色、背景、边框色、阴影色、文字内容颜色等发生改变时;

2、元素尺寸和位置不变时:重绘发生在元素尺寸和位置不变的情况下,只改变元素的外观属性,如背景颜色、字体颜色等;

3、元素隐藏时:将元素的visibility属性设置为hidden时,虽然会触发重排,但不会影响布局,只会触发重绘。

何时会引起回流?

1、添加或删除可见的Dom元素;

2、元素位置发生变化;

3、元素尺寸发生变化 (包括外边距、内边距、边距大小、高度和宽度等);

4、内容发送变化,比如文本变化或图片被另一个不同尺寸的图片代替;

5、浏览器窗口尺寸发生变化(因为回流是根据视口大小来元素位置和大小的)

回流和重绘的联系?

回流一定引起重绘,而重绘不一定会回流。

六、script标签async和defer

script 标签JS 执行顺序是否阻塞解析 HTMLDOMContentLoaded回调
<script>依次等待
<script async>先下载完先执行DOM未解析完时阻塞不等待
<script defer>先下载完所有defer再依次执行等待

1、默认情况下,遇到script标签会阻塞下面HTML的解析,先解析完成script标签里的内容,再继续执行解析。(同步解析,依次进行)

2、async情况下,遇到script标签系统不会阻塞HTML的解析,而是创建一个异步路径来进行async脚本的解析。一边解析HTML一遍解析async,当async解析完毕后,系统才会阻塞HTML的解析并立即执行async script里的内容。(解析时不阻塞HTML解析,解析完毕执行时才阻塞HTML,两个解析相互独立进行)

3、defer情况下,不会阻塞HTML解析,直到HTML解析完毕后,defer在最后执行。(DOM元素渲染完毕后执行)

使用情景:

1、默认情况适合一般脚本的顺序执行;

2、async情况适合处理一些无需阻塞并且与DOM元素无关的操作。

(注:这种情况下,执行DOM元素的操作是不稳定的。当DOM元素很少时,可能async有时会比HTML晚解析慢,从而后执行,有时执行正常有时执行失败。但当DOM元素过大需要更多时间解析时,很可能async都已经开始执行了,但DOM还未解析完毕,当async里的代码操作DOM元素时,就可能出现获取不到DOM元素的情况)

3、defer情况适合需要在页面加载完毕后的代码执行,如需要操作DOM的脚本执行。

七、普通函数和箭头函数的区别

1、this绑定:

箭头函数:没有自己的this上下文,而是继承父类的this; (不能使用apply、bind、call来修改this指向)(箭头函数的this在定义时就已确定,之后不得修改)

普通函数:this取决于函数的调用方式。(补充:在全局状态下,非严格模式this是window,严格模式下this是undefined)

2、arguments实参对象

箭头:不包含arguments;

普通:包含arguments对象 (补充:非严格模式下,实参arguments是和形参进行映射的,修改其中一个对应都会改变;严格模式下,并未有映射,修改其一不会修改另一个对应)

3、作用域和闭包

箭头:遵循作用域规则 (块级作用域)

普通:形成闭包

八、JS闭包

JavaScript的普通函数就是一个闭包。

1、闭包特点

1)函数嵌套函数

2)内层函数可以访问外层函数的变量和参数

2、闭包作用

1、防止变量和参数被垃圾回收机制回收(变量持久化)

2、防止变量和参数被外部污染 (变量只在内部可访问)

3、闭包风险

滥用可能会造成内存泄漏。

4、运用场景
1)常见闭包
    function makeCounter() {
        let counter = 0
        return function () {
            counter++
            console.log(counter)
        }
    }

    const counter = makeCounter()
    counter()  //1
    counter()  //2
    counter()  //3
2)实现模块化
    const myModule=(function () {
        let count=0

        function increment(){
            count++
        }

        function reset(){
            count=0
        }

        function getCount(){
            return count
        }

        return {
            increment,
            reset,
            getCount
        }
    })()

    myModule.increment()
    console.log(myModule.getCount())  // 1

    myModule.reset()
    console.log(myModule.getCount())  // 0
3)缓存函数
     function memorize(fn) {
        const cache = {}

        return function (arg) {
            if (arg in cache) {
                console.log("已调用缓存数据")
                return cache[arg]
            } else {
                const result = fn(arg)
                cache[arg] = result
                return result
            }
        }
    }

    function expensiveCalculation(num) {
        console.log("正在计算" + num + "的阶乘...")
        let result = 1
        for (let i = 2; i <= num; i++) {
            result *= i
        }
        return result
    }

    const memorizedCalculation = memorize(expensiveCalculation)
    console.log(memorizedCalculation(5))  //正在计算5的阶乘...  120
    console.log(memorizedCalculation(5))  //已调用缓存数据    120
4)封装私有变量
     function createPerson(name, age) {
        let privateName = name
        let privateAge = age

        function getName() {
            return privateName
        }

        function setName(newName) {
            privateName = newName
        }

        function getAge() {
            return privateAge
        }

        function setAge(newAge) {
            privateAge = newAge
        }

        return {
            getName,
            setName,
            getAge,
            setAge
        }
    }

    const person = createPerson("张三", 18)
    console.log(person.getName())  //张三
    console.log(person.getAge())   //18

    person.setName("李四")
    person.setAge(20)
    console.log(person.getName())   //李四
    console.log(person.getAge())    //20
5)实现函数柯里化
    function add(a, b, c, d) {
        return a + b + c + d
    }

    function curry(fn) {
        return function curried(...args) {
            if (args.length >= fn.length) {
                return fn.apply(this, args)
            } else {
                return function (...moreArgs) {
                    return curried.apply(this, args.concat(moreArgs))
                }
            }
        }
    }

    const curriedAdd = curry(add)
    console.log(curriedAdd(1)(2)(3)(4))   //10
    console.log(curriedAdd(1, 2)(3, 4))   //10
    console.log(curriedAdd(1, 2, 3, 4))   //10
7)防抖和节流
     function debounce(fn, wait) {
        let timeoutId
        return function (...args) {
            clearTimeout(timeoutId)
            timeoutId = setTimeout(() => {
                fn.apply(this, args)
            }, wait)
        }
    }

    function throttle(fn, wait) {
        let isThrottled = false
        return function (...args) {
            if (!isThrottled) {
                isThrottled = true
                setTimeout(() => {
                    fn.apply(this, args)
                    isThrottled = false
                }, wait)
            }
        }
    }

    function handleInput() {
        console.log("input changed")
    }

    const debouncedHandleInput = debounce(handleInput, 500)
    const throttleHandleInput = throttle(handleInput, 500)

    document.querySelector("input").addEventListener("input", debouncedHandleInput)
    document.querySelector("button").addEventListener("click", throttleHandleInput)

总结到此!

标签:function,知识点,闭包,return,log,混淆,console,解析,梳理
From: https://blog.csdn.net/qq_50909707/article/details/143823761

相关文章

  • AcWing 进阶课知识点模板梳理
    EK求最大流点击查看代码#include<bits/stdc++.h>#defineintlonglongusingnamespacestd;constintN=1005,M=20005,INF=1e8;intn,m,S,T;inth[N],e[M],f[M],ne[M],idx;intq[N],d[N],pre[N];boolst[N];voidadd(inta,intb,intc){e[idx]......
  • 猿人学web端爬虫攻防大赛赛题第6题——js 混淆 - 回溯
    题目网址:https://match.yuanrenxue.cn/match/6解题步骤看流量包。有两个参数需要得知它的加密逻辑。全局搜索url里的关键词api/match/6。只有一处,打上断点,刷新界面,触发断点。先看m参数的生成逻辑。"m":r(t,window.o)t:t=Date.parse(newDate());,时间戳window.o:是win......
  • 进程的知识点
    进程的基本概念进程是操作系统中的一个执行单位,代表正在运行的程序实例。每个进程都有自己独立的内存空间和系统资源,独立于其他进程运行。进程的生命周期包括创建、就绪、运行、等待和终止等状态。进程的创建与管理在操作系统中,进程的创建和管理通常通过系统调用实现,如fork(......
  • JAVA部分基础知识点(四)【持续更新】
    1.方法重写当子类觉得父类中的某个方法不好用,或者无法满足自己的需求时,子类可以重写一个方法名称、参数列表一样的方法,去覆善父类的这个方法,这就是方法重写。【注意:重写后,方法的访问,Java会遵循就近原则】方法重写的其它注意事项:重写小技巧:使用Override注解,他可以指定java......
  • 【文化课学习笔记】【化学】有机相关知识梳理
    有机相关知识梳理有机物的化学性质有机物主要化学反应高中有机主要反应(不涉及加聚、缩聚):烃三角涵盖了烷、烯、炔和卤代烃三种烃类的关系,可逆三角中的三类物质可以互相转化、醇醛酸酯化三角主要反应以连续氧化和酯化反应为特征,同时包含二者的逆反应(还原反应和水解反应)。从烷......
  • 带你一起全面了解关于Python网络爬虫的相关知识点!
     成长路上不孤单......
  • c语言知识点总结-字符串、思维导图
    字面串、字符串变量、字符串的读写、字符串中字符的访问、函数、字符串处理操作、字符串数组总结。文中链接:CSDNhttps://mp.csdn.net/mp_blog/creation/editor/143772084锦黎pro-CSDN博客锦黎pro擅长c语言知识点总结、思维导图,等方面的知识https://blog.csdn.net/jilipro?......
  • 【数学】线性代数知识点总结
    0.前言线性代数是数学的一个分支,线性代数的研究对象是向量、向量空间(又称线性空间),线性变换和有限维的线性方程组。即线性代数主要处理线性关系问题,线性关系即数学对象之间的关系是以一次形式来表达的。线性(Linear)是指量与量之间按比例、成直线的关系,在数学上可以理解为一......
  • 鸿蒙Navigation知识点详解
    Navigation是路由导航的根视图容器,一般作为页面(@Entry)的根容器,包括单栏(Stack)、分栏(Split)和自适应(Auto)三种显示模式。Navigation组件适用于模块内和跨模块的路由切换,通过组件级路由能力实现更加自然流畅的转场体验,并提供多种标题栏样式来呈现更好的标题和内容联动效果。一次开发,多......
  • vite3+vue3 实现前端部署加密混淆 javascript-obfuscator
    安装pnpminstalljavascript-obfuscator安装之后在项目根目录新建一个obfuscator.js在obfuscator.js写入以下代码直接复制粘贴`/**@用法vite打包完成后,使用命令行nodejs执行本文件:nodeobfuscator.js它会挨个把里面的js文件做混淆然后替换@说明本质就是依......