Skip to content
字数
2692 字
阅读时间
11 分钟

复习与学习,就是思考这些概念是什么, 有什么联系,用到实际中是怎么样的,然后去实践验证

要分清 前端和后端客户端和服务端

前端服务器不属于前端, 前端服务器 是后端. 所以nextjs是前端+前端服务器的全栈框架 而react web 是纯前端框架

学习计算机的目的是认识已有计算机系统, 理解的核心是图灵完备,'调用'和'运算'的实现就是满足图灵完备, 一副 跳转给不同算术单元传输信号的 逻辑电路图

学习编程(语言)是为了读懂计算命令,描述计算命令,理解的核心就是语法(结构体和指针,对象和引用,回调和上下文)

学习程序设计是想如何实现有想要的功能的程序,理解的核心是如何组织拆分资源和功能,前端的话资源主要是ui, 后端的话资源主要是数据

三种目的不同,实现行为方式不同,读别人的代码就是自顶向下理解,什么功能,怎么传数据,电路怎么跑 学习就是认知,将原本没有概念的抽象概念在自己的脑子里映射成直观的图

1、文件对于代码运行的影响

在计算机中,文件只是为了人区分用途分割出来的代码片段,对于计算机来说将代码分割成文件还是不分割都是一样的,所以同一后缀名的文件,分割出来对于计算机执行代码没有任何(语法)意义,例如在 React 中声明组件,单独创建出一个 tsx 文件,将其用帕斯卡命名法( PascalCase 也称为大驼峰命名法)命名后,还需要在文件内声明其(文件名)是一个组件,文件名在这里只起到一个为计算机标明位置,为人表面结构的功能 React.FC的功能

2、回调函数的判断依据

函数是否被称为回调函数取决于它被使用的方式。*

回调函数是指在编程中,将一个函数作为参数传递给另一个函数,并在后者执行完特定任务后,调用传入的函数,以完成某些操作或通知。回调函数通常用于异步编程中,用于处理异步操作的结果或事件。

function funcA(param) {
  console.log(param); 
}

function funcB() { 
  return "Hello"; 
} // 在funcA的参数中调用funcB,并将其返回值作为参数传递给funcA
funcA(funcB());

在这段代码中,并没有使用回调函数。回调函数通常是作为参数传递给其他函数,并在特定的事件发生或条件满足时由其他函数调用。在这段代码中,虽然 funcB 返回的值被作为参数传递给了 funcA,但 funcB 并不是一个回调函数。

实际上,在这段代码中,funcB 只是一个简单的函数,它没有被传递给其他函数作为参数,并且没有在某个事件发生时被调用。因此,它不是一个回调函数。

function a(a: number): number { 
  console.log(a); return 64; 
} 

function b(i: number): void {
  console.log(i); 
} // 先声明函数a和函数b,然后再调用
b(a);

在这段代码中,没有使用回调函数。回调函数是指在异步操作完成后执行的函数,通常作为参数传递给其他函数,在异步操作完成时被调用。

在这个代码片段中,函数 b 被调用并传递了函数 a 作为参数,但是 b 函数本身没有在异步操作完成后调用传入的函数 a。相反,它将传入的参数直接打印出来。

以下是将函数 a 作为回调函数的一个示例:

typescript
function a(a: number): number {
    console.log(a);
    return 64;
}

function b(callback: (i: number) => void): void {
    const result = callback(42); // 调用传入的回调函数
    console.log("Result:", result);
}

// 将函数a作为回调函数传递给函数b
b(a);

在这个示例中:

  • 函数 b 接受一个回调函数作为参数,这个回调函数的类型为 (i: number) => void,即接受一个 number 类型参数并且没有返回值。
  • 在函数 b 中,调用传入的回调函数,并将参数 42 传递给它。
  • 在函数调用的结果中,将函数 a 作为回调函数传递给了函数 b,这样在函数 b 内部就可以调用函数 a。 在 JavaScript 中,通常将一个函数称为回调函数,当它满足以下条件之一时:
  1. 作为参数传递给其他函数,并在其他函数内部被调用。
  2. 在某个事件发生时被作为事件处理函数调用。

因此,要判断一个函数是否是回调函数,可以根据上述条件进行检查。例如,可以检查函数是否作为参数传递给其他函数,或者是否被用作事件处理函数。

以下是一个示例,演示如何判断一个函数是否是回调函数:

javascript
function callbackFunction(param) {
    console.log(param);
}

function higherOrderFunction(callback) {
    // 在这个高阶函数中调用回调函数
    callback("This is a callback");
}

// 将函数callbackFunction作为回调函数传递给higherOrderFunction
higherOrderFunction(callbackFunction);

// 另一个示例,判断函数是否用作事件处理函数
document.addEventListener('click', callbackFunction);

函数是否被称为回调函数取决于它被使用的方式。

回调函数是一个术语,用于描述在某些情况下被传递给其他函数的函数。这种情况包括被用作事件处理函数、异步操作的回调函数、或者作为高阶函数的参数。但是,只要一个函数被高阶函数作为参数传递,并不意味着它就是一个回调函数。它还需要在高阶函数内部被调用,才能满足回调函数的定义。

实际上,判断一个函数是否是回调函数,需要综合考虑两个方面:

  1. 这个函数是否被传递给其他函数作为参数。
  2. 这个函数是否在其他函数内部被调用。

3.为什么 JavaScript 要加分号(良好的代码编写习惯通用实践)

最常见的错误是 某行没加分号的代码和下一行的小括号连起来,被当成一个调用函数的语句,例如:

js
let a = 3
(function() {
    console.log('IIFE')
})()
// 实际上会被解释为:let a = 3(function() { console.log('IIFE') })();

以下是以下常用的编写习惯(通用实践)

有意义的命名
  • 变量和函数:使用有意义且描述性的名称,避免使用缩写和模糊的名称。
  • 常量:使用大写字母和下划线来命名常量,例如 MAX_COUNT
注释
  • 必要的注释:在复杂或重要的代码块上添加注释,解释代码的意图和逻辑。
  • TODO 注释:使用 TODO 注释标记未来需要改进或实现的地方。
遵循最佳实践
  • 避免全局变量:尽量减少使用全局变量,使用局部作用域和闭包来封装变量。
  • 模块化代码:将代码分成小的、可重用的模块或函数,每个模块或函数只做一件事(单一职责原则)。
错误处理
  • 异常处理:在可能出错的地方使用 try...catch 语句,并提供有意义的错误信息。
  • 输入验证:在处理用户输入时,进行充分的验证和消毒,防止安全漏洞。
JavaScript 和 TypeScript
  • 严格模式:使用 "use strict"; 开启严格模式,帮助捕获常见的错误。
  • 箭头函数:尽量使用箭头函数来保持 this 绑定的一致性。
  • 类型注解:在 TypeScript 中,尽量为函数和变量添加类型注解,提高代码的可靠性。
HTML
  • 语义化标签:使用语义化标签(如 <header>, <article>),提高页面结构的可理解性和可访问性。
  • 有效的属性:为标签添加必要的属性(如 alt 属性用于 <img>),提高页面的可访问性。
命名约定

遵循 Java 的命名约定,类名使用大驼峰命名法(如 MyClass),方法名和变量名使用小驼峰命名法(如 myMethod)。

4.关于 return 语句的报错

return 语句后,JavaScript 引擎会自动插入一个分号,因为它认为 return 语句已经结束。所以实际上它等同于:

js
console.log( function getValue() {
    return; // 分号被自动插入
    {
        value: 42
    };
}())

为了让 return 返回一个对象字面量,可以将对象字面量紧跟在 return 之后,或者使用括号包裹对象字面量。

js
console.log( function getValue() {
    return {
        value: 42
    };
}())

或者

js
console.log( function getValue() {
    return (
    {
        value: 42
    });
}())
js
const input1 = document.getElementById('input1')

  

// let timer = null

// input1.addEventListener('keyup', function () {

//     if (timer) {

//         clearTimeout(timer)

//     }

//     timer = setTimeout(() => {

//         // 模拟触发 change 事件

//         console.log(input1.value)

  

//         // 清空定时器

//         timer = null

//     }, 500)

// })

  

// 防抖

function debounce(fn, delay = 500) {

    // timer 是闭包中的

    let timer = null

  

    return function () {

        if (timer) {

            clearTimeout(timer)

        }

        timer = setTimeout(() => {

            fn.apply(this, arguments)

            timer = null

        }, delay)

    }

}

  

input1.addEventListener('keyup', debounce(function (e) {

    console.log(e.target)

    console.log(input1.value)

}, 600))



//addEventListener方法接收一个事件和事件发生后所执行的方法,因为想在 input1.addEventListener 中传入的方法经过防抖方法处理,所以在定义防抖函数时有一个形参是函数,且为了让addEventListener接收到函数必须返回一个经过处理后的函数,而不是仅仅只执行一遍逻辑

贡献者

The avatar of contributor named as sunchengzhi sunchengzhi

文件历史

撰写