ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

JS函数与jQuery核心原理:从this指向到DOM操作一次讲透

JS函数与jQuery核心原理:从this指向到DOM操作一次讲透 入行那几年我最大的感受是很多人学前端是从 jQuery 开始的用起来是真快但面试一问为什么就卡壳。后来回头系统补 JS 函数基础才发现当年那些能跑就行的代码里藏着大量原理问题。这篇就把 JS 函数与 jQuery 核心知识点放在一起梳理一遍讲清楚背后的逻辑、常见坑和实战里的高频场景。内容适合两类人一是刚入门没多久、想系统整理知识体系的新手二是写过不少业务代码但总觉得基础不牢的初中级前端。先说清楚这个选题的价值。函数是 JavaScript 的基石不管是普通函数、箭头函数、回调函数还是高阶函数前端业务里天天都在碰。jQuery 虽然现在新项目用得少了但存量项目、老系统、面试题里它依然是高频名词而且它封装 DOM 操作、事件、Ajax 的思路对理解现代前端框架的设计也有帮助。一句话函数解决代码怎么写jQuery 解决页面怎么操作两者串起来就是一套完整的前端基础能力。1. 整体设计思路为什么把函数和 jQuery 放在一起学1.1 函数是地基jQuery 是脚手架前端开发里有个很形象的比喻原生 JS 是地基jQuery 是脚手架。地基决定你能盖多高的楼脚手架决定你干活快不快。很多人直接学脚手架而不碰地基短期能出活但遇到脚手架覆盖不到的场景就完全不会了。jQuery 的底层全部是 JS 函数。$() 本身就是一个函数调用$(selector) 传入选择器字符串返回的是经过包装的 DOM 对象集合。click()、on()、each() 这些方法背后对应的分别是事件处理函数、遍历回调函数。所以函数概念不清jQuery 代码只能靠记 API 记用法换一个场景就懵函数概念通了jQuery 的源码思路和 API 设计逻辑就会变得可推导。我整理这套知识点时刻意不把两样东西分开讲。函数讲完立刻接 jQuery 里对应的用法这样你能直观看到原来 jQuery 里这个 API 就是函数思想的落地。1.2 这套知识到底覆盖了哪些高频场景从平时提的问题里就能看出重点方向函数声明、箭头函数写法、回调函数、this 指向、jQuery 选择器、DOM 操作、事件绑定、Ajax 交互。这些词几乎覆盖了前端日常开发 70% 以上的基础工作。再配合一些具体场景看js 忽略大小写的字符串比较、js 判断字符串是否包含、jquery 根据 name 获取对象、jquery 第一个子元素、前端三级联动、输入车牌前端页面、动态表格合并、前端传参。每个看起来是独立的搜索问题拆开来看背后就是字符串处理函数、选择器定位、DOM 遍历、事件绑定和数据传递。这套内容本质上是一张前端基础能力清单。学完你能做到给一段业务需求知道用哪些函数和 API 组合实现遇到 DOM 操作和事件交互能写出兼容性好、可维护的代码面试被问到函数与 this 相关的基础题能讲清楚原理而不只是背答案。2. JS 函数核心知识点拆解2.1 函数声明与函数表达式提升机制的坑我见过不少人在函数声明和函数表达式上栽过跟头原因就是没理解 JavaScript 的变量提升机制。函数声明是最常见的写法function sayHello() { console.log(hello); }函数表达式则是把函数赋给变量const sayHello function() { console.log(hello); };两者最大的区别在提升机制。函数声明会被整体提升到作用域顶部你可以在声明之前调用它。函数表达式不一样只有变量声明被提升赋值操作留在原地所以在赋值之前调用会报错。// 正常输出 greet(); function greet() { console.log(声明式函数可用); } // 报错greet is not a function hello(); const hello function() { console.log(表达式函数不可用); };这个细节看起来简单但实际业务里如果你在模块顶层用函数表达式给某个变量赋值而其他文件代码在加载顺序上更早执行并调用了它就会出现找不到函数的诡异问题。排查思路就是先判断你用的是声明式还是表达式。2.2 箭头函数写法变了this 也跟着变箭头函数是 ES6 引入的写法现在项目里几乎处处都用。它的核心特点有两个简写和 this 绑定规则。先看写法// 传统函数 function add(a, b) { return a b; } // 箭头函数简写 const add (a, b) a b; // 只有一个参数可以省略括号 const double x x * 2; // 没有参数必须保留括号 const random () Math.random();箭头函数里的 this 是词法绑定定义它的时候 this 指向就已经确定了而不是在调用时动态确定。这是它和普通函数最大的不同。普通函数里this 由调用方式决定。对象方法里调用 this 指向该对象单独调用 this 指向全局对象。箭头函数则固定为定义箭头函数所在作用域的 this。const obj { name: test, normalMethod: function() { setTimeout(function() { console.log(this.name); // undefined此时 this 指向全局 }, 100); }, arrowMethod: function() { setTimeout(() { console.log(this.name); // test箭头函数捕获了外层 this }, 100); } };这个特性在写事件回调、定时器、Ajax 回调时非常实用。但注意箭头函数不能作为构造函数使用也没有自己的 arguments 对象需要这些功能时还是要回到普通函数。2.3 回调函数与异步流程事件和 Ajax 的基础回调函数是前端最基础也最核心的异步处理方式。所谓回调就是把一个函数作为参数传给另一个函数由后者在合适的时机调用。例子很好找$(#btn).click(function() { alert(点击了按钮); });这里 click() 接受的匿名函数就是回调函数。浏览器在按钮被点击时自动调用它。Ajax 更明显$.ajax({ url: /api/data, success: function(data) { console.log(请求成功, data); }, error: function(err) { console.log(请求失败, err); } });success 和 error 里的函数都是回调它们不知道什么时候会被调用但知道成功时执行哪个、失败时执行哪个。理解回调函数的关键在于理解执行时机。回调函数不是定义完马上就执行而是要等某个条件满足。条件可以是用户点击、请求返回、定时器到时间。所以写回调的时候不要假设里面的数据在下一行代码就能用数据什么时候到取决于触发条件什么时候满足。回调地狱也是这个知识点逃不开的痛点。多层嵌套的回调会让代码变成倒金字塔$.ajax({ url: /api/user, success: function(user) { $.ajax({ url: /api/order?user user.id, success: function(orders) { $.ajax({ url: /api/detail?order orders[0].id, success: function(detail) { console.log(detail); } }); } }); } });解决思路就是 Promise 和 async/await但现在用 jQuery 3.x 也可以配合 Promise 来处理。核心原理还是函数与回调只是包装方式变了。2.4 this 指向与 apply/call/bind前端面试必考题this 是 JS 函数里最绕的一个知识点面试几乎必问。我的经验是用一张表记清楚调用方式与 this 的关系。调用方式this 指向普通函数调用全局对象浏览器里是 window严格模式下是 undefined对象方法调用该对象构造函数调用new新创建的实例对象call/apply/bind 调用手动指定的对象箭头函数定义时所在作用域的 thiscall、apply、bind 都是 Function.prototype 上的方法作用是手动指定函数执行时的 this 指向。function introduce(age, city) { console.log(this.name is age years old, from city); } const person { name: 张三 }; introduce.call(person, 25, 北京); introduce.apply(person, [25, 北京]); const boundIntroduce introduce.bind(person, 25, 北京); boundIntroduce();区别很简单call 是逐个传参apply 是数组传参bind 不立即执行而是返回一个新函数后续调用时 this 已经被永久绑定。实战里 bind 用得最多的地方是事件回调里固定 this。用 Vue 或 React 的注意点其实都是同一套逻辑只是框架帮你做了处理。建议动手写几遍 apply/call/bind 的模拟实现面试的时候能讲清楚内部机制印象分完全不同。3. jQuery 核心知识点拆解选择器、DOM 与事件3.1 选择器一张表过一遍高频写法jQuery 选择器是它最强大的能力之一基于 CSS 选择器语法并做了扩展。平时开发用的最多的写法就这么几类需求写法按 id 获取$(#id)按 class 获取$(.class)按标签获取$(div)按属性获取$([nameusername])按属性前缀获取$([name^user])第一个子元素$(ul li:first-child)最后一个元素$(ul li:last)表单元素$(input:checked)值得展开说两个高频搜索。第一个是jquery 根据 name 获取对象写法就是 $([nameusername])。这里注意引号不能省属性值一定要用引号包起来不然选择器解析会出问题。第二个是jquery 第一个子元素。很多新手会直接写 $(div:first)这取的是页面上第一个 div不是某个 div 里的第一个子元素。要取某个容器下的第一个子元素正确写法是 $(#container).children().first()或者 CSS 选择器 $(#container :first-child)。这两个写法本质不同children() 只考虑直接子元素:first-child 是匹配作为父亲的第一个子元素的元素。理解了这个差异选择器就算入门了。3.2 DOM 操作与样式控制jQuery 封装了一整套 DOM 操作方法核心就是增删改查。文本和 HTML 内容的操作$(#title).text(新的标题); // 设置纯文本 $(#content).html(p新的段落/p); // 设置 HTML const txt $(#title).text(); // 读取文本样式的操作也很简单$(#box).css(color, red); $(#box).css({ color: red, fontSize: 14px });class 的操作更推荐用 addClass、removeClass、toggleClass而不是直接改 css 属性。理由很简单class 控制样式可维护性更好也方便和 CSS 联动。比如按钮的选中状态用一个 .active 类切换比直接写背景色代码要清晰得多。属性操作里容易被忽略的是 prop 和 attr 的区别。处理 checked、disabled、selected 这类布尔属性时用 prop$(input[nameagree]).prop(checked, true); $(#btn).prop(disabled, true);attr 处理的是自定义属性或非布尔属性。实际项目里如果复选框勾选状态失灵十有八九是用了 attr 而不是 prop。这个坑我印象很深。3.3 事件绑定on/off 的正确打开方式jQuery 事件里最容易混的是 bind、live、delegate、on 这一套历史遗留方案。现在统一记一个结论jQuery 3.x 时代只用 on 和 off 就够了。// 绑定事件 $(#btn).on(click, function() { console.log(点击了); }); // 解绑事件 $(#btn).off(click);on 真正的高级用法是事件委托。动态生成的元素直接绑定事件是无效的因为绑定发生在元素还不存在的时候。用事件委托才能让未来生成的元素也能响应事件。// 直接绑定动态添加的元素点击无效 $(.item).on(click, function() { console.log(this); }); // 事件委托父容器监听动态子元素也能触发 $(#list).on(click, .item, function() { console.log($(this).text()); });这里 this 指向当前点击的 DOM 元素如果想用 jQuery 方法需要先转成 $(this)。写事件回调时如果发现动态生成的元素点击没反应先检查是不是没有用事件委托。这是项目排查里非常常见的场景。3.4 Ajax 请求与数据交互jQuery 的 Ajax 是老牌功能$.ajax 是核心方法$.get、$.post、$.getJSON 是简化封装。$.ajax({ url: /api/login, type: POST, contentType: application/json, data: JSON.stringify({ username: admin, password: 123456 }), dataType: json, success: function(res) { console.log(res); }, error: function(xhr, status, error) { console.log(请求失败, error); } });写 Ajax 请求时建议固定几个习惯。第一POST 请求如果后端接口要求 JSON 格式contentType 必须设置为 application/jsondata 用 JSON.stringify 序列化。第二dataType 声明成 json 可以让 jQuery 自动完成响应解析。第三success 和 error 都要写即使只是打印日志至少排查的时候有线索。前端的传参在这个环节体现得最集中。除了 URL query string 拼参数POST body、请求头、路径参数都是传参的常见方式。遇到前端传参相关的问题先搞清楚后端接口文档定义的是哪种接收方式再用对应的方法传就能避免大量 400 错误。跨域问题这里也顺便提一句。老项目里最常见的跨域方案是 JSONP$.ajax 里通过 dataType: jsonp 触发。但 JSONP 只支持 GET 请求。新项目建议优先考虑 CORS 方案能让前端代码更简洁。4. 热门搜索词背后的实战场景还原4.1 高频搜索题逐个击破忽略大小写、字符串包含、第一个子元素搜索里有一批基础题实际是一类问题就是字符串与 DOM 的边界处理。js 忽略大小写的标准做法是统一转换后再比较function equalsIgnoreCase(str1, str2) { return str1.toLowerCase() str2.toLowerCase(); }注意中文没有大小写概念toLowerCase 对中文不产生影响。特殊场景下可以用 toLocaleLowerCase 处理特定语言字符但常规业务用 toLowerCase 就够。js 判断字符串是否包含const str hello world; const hasWord str.includes(world); // true // 忽略大小写的包含判断 const hasIgnoreCase str.toLowerCase().includes(WORLD.toLowerCase());includes 是 ES6 方法返回布尔值。旧浏览器兼容性要求高时可以用 indexOfconst hasWord str.indexOf(world) ! -1; // true这两个其实是同一类问题的两种写法。业务里还有个常见需求是用本地 JS 覆盖原 JS或注入脚本优先执行这类场景本质上讨论的是脚本执行顺序和覆盖时机涉及 DOMContentLoaded 事件、脚本顺序控制这些也和 函数与事件循环 的概念有关思路是搞清楚哪些代码先执行、哪些后执行。4.2 前端面试题里的函数考点防抖、节流与柯里化面试题里函数相关的高频题绕不开防抖、节流、柯里化。它们的核心都是用函数操作函数。防抖的场景是输入框实时搜索、窗口 resize。核心逻辑是在一定时间内如果事件再次触发就重置计时器。function debounce(fn, delay) { let timer null; return function(...args) { if (timer) clearTimeout(timer); timer setTimeout(() { fn.apply(this, args); }, delay); }; } const search debounce(function(value) { console.log(搜索, value); }, 500);这里用到了 apply 来确保 fn 执行时的 this 指向和原来一致同时在参数传递上用剩余参数 ...args 收集所有参数。一个防抖函数把函数、参数、this 的知识点全串起来了。节流的场景是滚动加载、按钮防连点。核心逻辑是固定时间内只执行一次。function throttle(fn, interval) { let last 0; return function(...args) { const now Date.now(); if (now - last interval) { last now; fn.apply(this, args); } }; }这类函数写一遍、背思路本质上是在考察你对函数是一等公民的理解程度。函数可以作为参数传入、作为返回值传出这就是高阶函数的概念。4.3 前端小功能拆解车牌输入、三级联动、动态表格合并这几个都是实际业务需求也是面试可能考的动手题。车牌输入框的核心是格式校验。中国车牌一般是省份汉字 字母 数字的组合常见正则大概是function isValidPlate(plate) { const reg /^[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领][A-HJ-NP-Z][A-HJ-NP-Z0-9]{4,5}[A-HJ-NP-Z0-9挂学警港澳]$/; return reg.test(plate); }实际业务要注意的是输入过程中的过滤比如禁止输入特殊字符、自动转大写。这类功能考验的是对字符串函数的熟悉度正则 replace toUpperCase 的组合。三级联动是经典的省市区选择。核心思路是监听上级变化重置并加载下级数据$(#province).on(change, function() { const val $(this).val(); $(#city).empty().append(option value请选择城市/option); $(#district).empty().append(option value请选择区县/option); // 根据 val 异步获取城市列表 loadCities(val); });动态表格合并是考察 DOM 操作和遍历的题。比如按某个列的值合并相同行的单元格逻辑是先遍历所有行比较相邻行的目标列值相同则设置 rowspan 并隐藏后一行。function mergeCell(tableSelector, columnIndex) { const rows $(tableSelector).find(tr); rows.each(function(index, row) { if (index 0) return; // 跳过表头 const current $(row).find(td).eq(columnIndex).text(); const prev $(rows[index - 1]).find(td).eq(columnIndex).text(); if (current prev) { $(row).find(td).eq(columnIndex).remove(); const prevCell $(rows[index - 1]).find(td).eq(columnIndex); prevCell.attr(rowspan, Number(prevCell.attr(rowspan) || 1) 1); } }); }这个实现里用到了 each 回调函数、eq 定位元素、attr 修改属性基本就是 jQuery 核心 API 的综合应用。建议自己动手调一遍比记十个 API 都管用。4.4 环境问题与工程化联动命令找不到、传参与组件化搜索词里还有一类很有意思的pnpm 无法将...识别为 cmdlet、claude 无法识别、make 无法识别这类错误很多新手会误以为和 JS 或 jQuery 有关。其实这是 Windows 环境下的 PATH 配置问题意味着你敲的命令在系统目录和项目 node_modules 的 .bin 目录里没有被识别。排查思路很简单确认工具是否已安装确认安装目录是否被加入 PATH确认终端是否重启过。多数情况下执行pnpm --version如果提示找不到说明 pnpm 的全局安装目录没被识别。给刚学前端的人一个建议环境问题不急背命令先理解 PATH 的概念再配合 npm/pnpm 全局目录的配置这类问题就能自己解决。如果继续往工程化走会碰到前端传参前端组件库前端 SDK这些词。组件化、SDK 封装本质都是函数与模块的组合。你封装一个组件其实就是封装一个函数只是它返回的是界面你封装 SDK就是把一堆相关函数按功能组织成模块。所以说函数学透了后面学框架和组件方案会轻松很多。5. 避坑指南与学习路线建议5.1 我自己踩过的几个典型坑这些年踩过的坑不少挑几个对新手最有借鉴意义的说说。第一个是 jQuery 对象和 DOM 元素混用。$(#btn) 拿到的是 jQuery 对象document.getElementById(btn) 拿到的是 DOM 元素。jQuery 对象可以用 .text()、.css() 等方法DOM 元素只能用原生的 textContent、style。如果混用代码会报 xxx is not a function。第二个是链式调用的中断问题。jQuery 的大部分方法返回的都是 jQuery 对象所以可以一直点下去。但使用某些方法比如 .each() 时返回值会变成数组或对象链就断了。我的习惯是遇到链式调用报错先拆分再排查。第三个是异步回调里的数据问题。Ajax 成功回调里拿到的数据在回调外面访问是 undefined。新手最容易踩请求发出后立即去读全局变量却忘了请求是异步的。let userData null; $.ajax({ url: /api/user, success: function(data) { userData data; // 这里赋值 } }); console.log(userData); // 这里可能还是 null因为请求还没返回调试这类问题我的经验是在 success 回调里打日志先确认数据是否到达再排查数据处理的逻辑。把同步和异步的执行顺序理清楚很多诡异问题就不攻自破了。5.2 从 jQuery 过渡到现代前端生态的建议现在很多新项目已经不用 jQuery 了React、Vue、小程序是主流。那 jQuery 还有没有必要学我的看法是学习价值依然很高但定位要清楚。如果你维护的是老项目jQuery 是必备技能这个没得选。如果你是新项目起步我建议把 jQuery 当作理解 DOM 操作和事件机制的辅助工具而不是主要依赖。两者过渡的重点在于原生 DOM API 的熟练度事件委托的思路Ajax 到 fetch/axios 的迁移。比如 jQuery 里的 $().on(click, .item, handler) 在原生里写就是 addEventListener 配合事件冒泡判断 target。document.querySelector(#list).addEventListener(click, function(e) { if (e.target.matches(.item)) { console.log(e.target); } });理解了 jQuery 的封装意图再看现代框架和原生 API会发现很多东西都是相通的。函数的基础没变DOM 操作的本质没变变的只是写法。最后再分享一个我自己常用的学习方法任何前端知识点都先用这段代码解决什么问题、用了哪些函数、函数的参数和返回值是什么三连问去过一遍。这是我在大量踩坑之后总结出的最有效的过滤规则知道自己在用什么远比会抄一段代码更能走得远。表面上你学的是 JS 函数和 jQuery实际上建立的是前端问题域里最底层的观察方法。这种东西一旦形成后面遇到再新的技术都不会慌。
返回列表