个人记录 --- Js红宝书的知识点(持续更新)

本文围绕JavaScript编程基础知识展开,讨论了异步和defer属性的应用、
摘要由CSDN通过智能技术生成

前言

本人最近在看Js红宝书,由于书籍太厚担心有些知识点看完不复习会忘记,所以打算写个博客记录下。

=========================================================================

正片开始

Q:大家都知道将js代码写在<body>中页面内容后面,不会阻塞页面渲染。那当js代码写在head中时,要也想达到不会阻塞页面渲染的效果要如何操作呢?

A:使用 script 中的async或者defer属性,这两个属性会告诉浏览器立即开始下载,二者都只适用于外部脚本。

区别是 defer 会把脚本推迟到文档渲染完毕后再根据出现顺序执行,async 则是异步加载,不需要等待其他脚本同时也不阻塞文档渲染,自然也不能保证脚本的执行顺序。


Q:关于<noscript>如何使用,何时使用?

A:  <noscript> 包含除<script>外任何可以出现在<body>中的代码,当浏览器不支持脚本或者浏览器对脚本的支持被关闭,二者任一条件被满足时,就会渲染 <noscript> 中的代码。


Q:声明变量的三个关键字 var let const的区别

A:

  1. var会进行变量提升,var可以重复声明,var声明的范围是函数作用域,var 在全局作用域声明的变量会成为window 对象的属性
  2. let 和 const 不会进行变量提升,不可以进行重复声明且声明范围为块级作用域,在全局作用域声明的变量不会成为window 对象的属性
  3. const声明变量时必须同时初始化变量,且之后不允许修改。(当然,如果 const 变量引用的是一个对象,那么修改对象的内部属性是可以的)

小tips: 在let 声明前的执行瞬间为 “ 暂时性死区” ,在此阶段引用任何后面才声明的变量都会报错


Q: 基本类型和引用类型 如何确定?

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

      可以使用 typeof 确定基本类型,不过有个例外 Null 会返回 “object”

      基本类型外的数据也可以使用typeof, function会返回function,object会返回object。

      引用类型可使用 instanceof,constructor,object.prototype.toString()等方法来确定。

      eg:

let date = new Date();  
console.log(date instanceof Date); // 输出 true  
console.log(date.constructor === Date); // 输出 true  
console.log(Object.prototype.toString.call(date)); // 输出 "[object Date]"

let arr = [];  
console.log(arr instanceof Array); // 输出 true
console.log(arr.constructor === Array); // 输出 true
console.log(Object.prototype.toString.call(arr)); // 输出 "[object Array]"

   基本类型都储存在栈中,引用类型的引用储存在栈中,value储存在堆中。


Q:object实例有哪些属性和方法

A:

  • constructor:用于创建当前对象的函数
  • hasOwnProperty( propertyName:string ):判断当前对象实例上是否存在给定的属性(就是看这个属性是不是对象本身的,不包括原型链继承的)
  • isPrototypeOf( object ):  判断当前对象是否是另一个对象的原型(代替原_proto_属性)
  • propertyIsEnumerable( propertyName:string ):判断给定的属性是否可以使用for-in语句枚举(就是看这个属性是不是对象本身的可枚举的,不包括原型链继承的。如果一个属性是对象,那它就是不可枚举的,就会返回false)
  • toString():返回对象的字符串形式
  • toLocaleString():返回对象的字符串形式,该字符串反映对象所在的本地化执行环境
  • valueOf():返回对应的字符串、数值或布尔值表示。(通常与toString()返回值相同)

Q:垃圾回收

A:Js是使用垃圾回收的编程语言。垃圾回收是周期性的,每隔一段时间垃圾回收程序就会自动运行。离开作用域的值会被自动标记为可回收,然后再垃圾回收期间被删除。

垃圾回收算法有标记清理和引用计数

标记清理:先给不适用的值加上标记,再回收它们的内存。(主流使用)

引用计数:记录每个值被引用的次数,引用一次就加一,当一个值引用的变量被其他值覆盖的时候就减一,数量为0时就回收。(在循环引用中会出现问题后被放弃使用)

如果内存中分配了很多变量,则可能造成性能损失。因此垃圾回收的时间调度很重要,重点是:无论什么时候开始收集垃圾,都要让它尽快结束。

(解除变量的引用不仅可以消除循环引用还对垃圾回收有帮助。)


Q:字符串操作方法

A:concat():拼接字符串,同 + 

      slice() 、substr() 和 substring():三者都是提取子字符串的方法,都接受1~2个参数。第一个参数表示子字符串起始位置。区别是

slice():第二个参数表示子字符串结束位置(不包含结束位)。当有参数是负数的时候,slice()会将所有负值参数都当做字符串长度+负参数值。

substr():第二个参数表示返回的子字符串长度。如有参数是负数的时候,substr() 会把第一个参数的负值转换为字符串长度+负参数值,第二个参数的负值转换为0。

subString():第二个参数表示子字符串结束位置(不包含结束位)。如有参数是负数的时候,subString() 会把所有负值转换为0,且这个方法会将较小的参数作为起点,较大的参数作为终点。 即:substring(3,0) 等价于 substring(0,3)

        trim():去除字符串前后空格,原字符串不受影响。衍生出来的方法有trimLeft()和trimRight(),分别去除字符串开始和结尾的空格。

        repeat():复制字符串,参数传的是数字,代表复制多少次.

        padStart()和padEnd(): 为字符串填充值,该方法接收两个参数。第一个参数为number类型,第二个参数为string类型(可为空)。

let k = "fooof"
console.log(k.padStart(4)) //输出 “fooof”
console.log(k.padStart(-1)) //输出 “fooof”
console.log(k.padStart(7)) //输出 “  fooof”
console.log(k.padStart(8,".")) //输出 “fooof...”

console.log(k.padEnd(7)) //输出 “fooof  ”
console.log(k.padEnd(8,".")) //输出 “fooof...”

Q: Math对象的属性和方法

A:

Math.PI:π

Math.ceil(): 向上取整。

Math.floor(): 向下取整。

Math.round(): 四舍五入。

Math.fround(): 返回数值最接近的 单精度(32)位浮点数。 Math.fround(0.4) =》0.4000000059604645

Math.random():返回0~1的随机数。

  • 如果想返回1~10的随机数则使用:num=Math.floor(Math.random()*10+1)。
  • 如果想返回2~10的随机数则使用:num=Math.floor(Math.random()*9+2)。
  • 可以推算出公式 num = Math.floor(Math.random()* totalNum + firstNum), totalNum代表范围内一共有多少整数,firstNum代表第一个整数。

Math.abs(x): 返回x的绝对值。

Math.sqrt(x): 返回x的平方根。

Math.pow(x,power): 返回x的power次幂。(忽然想起 a**2,代表a的平方)


Q:数组和伪数组的区别

A:

数组和伪数组的区别可以归结为以下几个方面:

  1. 类型与结构
    • 数组:数组是一种特殊的数据结构,用于在单一变量中存储多个值。这些值按照特定的顺序排列,可以通过索引来访问。数组的类型是Array
    • 伪数组:伪数组在结构上类似于数组,具有索引和length属性,但它们的类型并不是Array,而是Object。这意味着它们没有数组的方法,如push、shift、map等。常见的伪数组有函数的arguments对象和DOM元素集合(如通过document.getElementsByTagName获取的对象)。
  2. 属性与方法
    • 数组:具有内置的length属性和各种数组方法,如push(向数组末尾添加一个或多个元素,并返回新的长度)、shift(删除并返回数组的第一个元素)、map(创建一个新数组,其结果是该数组中的每个元素都调用一个提供的函数后返回的结果)等。
    • 伪数组:同样具有length属性,但这个属性是自定义的,并且在某些情况下可能不是number类型。伪数组不具有数组的方法,但可以使用Object的方法。
    • _proto_不同,数组的prototype有很多方法,伪数组的prototype只有几个方法
  3. 索引
    • 数组:索引是按顺序排列的整数,如0、1、2、3等。
    • 伪数组:索引也可以是非负整数,但它们在伪数组中作为对象的属性存在,因此会被当做字符串来处理。不过在实际应用中,我们可以将其视为非负整数串来理解。
  4. 动态性
    • 数组:其length属性是内置的,可以自动更新以反映数组中的元素数量。
    • 伪数组:length属性是自定义的,可能需要根据实际情况手动更新。
  5. 转换: 伪数组没有数组的方法,但结构类似,因此有时需要将其转换为真正的数组以便使用数组的方法。转换方法有多种,如使用Array.from(arrayLike)Array.prototype.slice.call(arrayLike)Array.prototype.splice.call(arrayLike, 0)Array.prototype.concat.apply([], arrayLike)等。

Q:生成器和迭代器

A:迭代器是一个按需创建的一次性对象。它定义了一个对象,在其元素上进行迭代。支持连续获取对象产出的每一个值。任何实现Iterable接口的对象都有一个 Symbol.iterator 属性,这个属性引用默认迭代器。

迭代器必须通过连续调用next()方法才可以连续获取值,这个方法返回一个InterableObject。这个对象包含done和value两个属性,分别代表是否还有更多值可以访问和迭代器当前的返回值。

class Counter {
    constructor(limit) {
        this.limit = limit;
    }
    
    [Symbol.iterator]() {
      let count = 1, limit = this.limit;
      return {
        next () {
            if(count <= limit) {
                return { done: false, value: count++ };
            } else {
                return { done: true, value: undefined };
            }
        }
      }
    }
}

Q: map 和 object的区别

A:

  1. 键的类型
    • Map的键可以是任意的数据类型,包括基本数据类型(如字符串、数字、布尔值)、对象以及函数。
    • Object的键则仅限于使用字符串(或Symbol,但在日常开发中字符串更为常见)作为键名。
  2. 有序性
    • Map中的键是有序的,会按照插入的顺序进行迭代。
    • Object的键则是无序的,虽然ES2015规范规定了键的插入顺序应与枚举顺序一致,但在实际开发中,并不能确保对象属性的顺序。
  3. 获取长度
    • Map具有一个size属性,可以直接获取Map中键值对的数量。
    • Object则需要通过Object.keys(obj).length来计算对象的属性数量,这种方式在性能上可能不如Map直接获取size属性。
  4. 迭代方式
    • Map是内置的可迭代对象,可以直接使用for...of循环进行迭代。
    • Object虽然也可以通过for...in循环进行迭代,但这种方式会遍历对象自身以及原型链上的所有可枚举属性,因此可能需要使用hasOwnProperty()方法来过滤掉原型链上的属性。另外,Object.keys()、Object.values()和Object.entries()方法也可以用来遍历对象的属性。
  5. 性能
    • 在频繁增删键值对的场景下,Map的性能通常优于Object。因为Map是专门为动态键值对设计的,而Object则是为了模拟类似于真实世界对象的结构而设计的。

可参考 前端JavaScript篇之map和Object的区别、map和weakMap的区别_前端map-CSDN博客


Q:https证书存放在什么位置?

A:浏览器端放在浏览器证书库中 

HTTPS是在HTTP和TCP之间通过加入SSL协议来实现安全的通信的


Q:js代码中,比如函数,它们都是异步的,是异步的就会创建一个回调,这个回调是谁来调用的?

A:在JavaScript中,当异步操作完成时,是JavaScript运行时环境(runtime environment)或特定的异步API(如浏览器或Node.js)负责调用回调函数。

具体来说:

  1. 浏览器环境:当你在浏览器中执行异步操作(如使用fetch API进行网络请求)时,浏览器会处理这个请求。一旦请求完成(无论是成功还是失败),浏览器会检查是否有回调函数与这个异步操作相关联。如果有,浏览器会调用这个回调函数,并将操作的结果(或错误信息)作为参数传递给回调函数。

  2. Node.js环境:在Node.js中,情况类似。Node.js的底层(基于libuv)和事件循环(event loop)负责处理异步操作。当异步操作完成时,Node.js会将其结果放入事件队列中。事件循环会监视这个队列,并在适当的时候将事件(包括完成的异步操作)和相关的回调函数取出执行。

因此,无论是浏览器还是Node.js,都是由JavaScript的运行时环境或特定的异步API来负责调用这些回调函数。这种机制允许JavaScript代码在等待异步操作完成时继续执行其他任务,从而提高应用程序的响应性和性能。


Q:js如何判断一个元素在视图区域内

A:

可以使用getBoundingClientRect()方法与窗口的尺寸进行比较,或者使用Intersection Observer API。下面分别介绍这两种方法:

1) 使用getBoundingClientRect()

getBoundingClientRect()方法返回一个DOMRect对象,该对象包含了元素的大小及其相对于视口的位置。通过比较这个对象的toprightbottomleft属性与视口的大小(window.innerHeightwindow.innerWidth),你可以判断元素是否在视口内。

function isElementInView(element) {  
    const rect = element.getBoundingClientRect();  
    const viewHeight = window.innerHeight || document.documentElement.clientHeight;  
    const viewWidth = window.innerWidth || document.documentElement.clientWidth;  
  
    // 检查元素是否在视口内  
    // 注意:这里假设“在视口内”意味着元素至少有一部分在视口内  
    return !(rect.bottom < 0 || rect.top > viewHeight || rect.right < 0 || rect.left > viewWidth);  
}  
  
// 使用  
const element = document.querySelector('#myElement');  
if (isElementInView(element)) {  
    console.log('元素在视图区域内');  
} else {  
    console.log('元素不在视图区域内');  
}

2) 使用Intersection Observer API

Intersection Observer API提供了一种异步检测目标元素与其祖先元素或顶级文档视窗(viewport)交叉状态的方法。这是处理这类需求的现代且推荐的方式,因为它不仅更简洁,而且性能更好。

function observeElementInView(element, callback) {  
    const observer = new IntersectionObserver((entries) => {  
        entries.forEach(entry => {  
            // isIntersecting 属性表明目标元素是否与视口交叉  
            if (entry.isIntersecting) {  
                callback(true);  
            } else {  
                callback(false);  
            }  
        });  
    }, {  
        root: null, // null 值表示视口  
        rootMargin: '0px', // 边界区域  
        threshold: [0] // 当元素与视口的交集达到或超过指定的百分比时,会触发回调函数  
    });  
  
    observer.observe(element);  
  
    // 记得在组件卸载或不再需要观察时取消观察  
    // observer.unobserve(element);  
    // 或者  
    // observer.disconnect();  
}  
  
// 使用  
observeElementInView(document.querySelector('#myElement'), isInView => {  
    if (isInView) {  
        console.log('元素现在在视图区域内');  
    } else {  
        console.log('元素现在不在视图区域内');  
    }  
});

在这个例子中,Intersection Observer API会在元素与视口交叉时(即元素进入或离开视口时)自动调用回调函数。通过设置threshold选项,你可以控制交叉多少百分比时才触发回调函数,但在这个例子中,我们使用了[0],意味着即使元素只有一点点与视口交叉,也会触发回调函数。如果你想要更精确地控制何时触发(比如元素完全在视口内时),你可能需要设置一个更合适的threshold值,或者使用多个threshold值。


Q:不同屏幕设置不同css

A:使用@media

/* 默认样式,适用于所有屏幕 */  
body {  
  background-color: lightblue;  
}  
  
/* 屏幕宽度小于600px时应用的样式 */  
@media screen and (max-width: 599px) {  
  body {  
    background-color: lightcoral;  
  }  
  .nav-menu {  
    display: none; /* 例如,隐藏导航菜单 */  
  }  
}  
  
/* 屏幕宽度大于或等于600px时应用的样式 */  
@media screen and (min-width: 600px) {  
  body {  
    background-color: lightgreen;  
  }  
  .nav-menu {  
    display: block; /* 显示导航菜单 */  
  }  
}

  • 47
    点赞
  • 45
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值