宝宝版js教学(百万字)超详细 对象基础
一、数组对象:JS 里的 “排队小火车”
梗版解析(碎碎念 + 代码穿插)
-
数组 = 排队小火车!是对象的 “亲兄弟”,但存储数据更规整(有序),性能还更好。
注意:JS 里火车能拉不同货(不同类型元素),但咱平时尽量拉同款货,看着舒服!
▼javascript复制代码// 造火车两种姿势: // 姿势1:先买空车厢(new Array())再装货 var arr1 = new Array(); arr1[0] = "悟空"; // 第1节车厢装悟空 arr1[1] = "八戒"; // 第2节车厢装八戒 // 姿势2:直接买装好货的火车(字面量,推荐!) var arr2 = ["悟空", "八戒", "沙和尚"]; // 一节车厢一个货 var 混搭火车 = [1, "2", true]; // 允许混搭,但不推荐
遍历数组 = 挨个查车厢:for 循环从第 0 节查到最后一节(length 是车厢总数):
▼javascript复制代码var arr = ["悟空", "八戒", "沙和尚"]; for (var i = 0; i < arr.length; i++) { console.log("第" + i + "节车厢:" + arr[i]); // 依次输出三个和尚 }
数组属性 = 火车说明书:
▼javascript复制代码var arr = [1,2,3]; console.log(arr.constructor); // 看造车图纸→function Array(){} console.log(arr.length); // 看车厢数→3
数组方法 = 火车操控按钮(重点!):
- push ():车尾加车厢,返回新长度:
▼javascript复制代码var arr = ["悟空", "八戒"]; var 新长度 = arr.push("沙和尚"); // 加一节沙和尚车厢 console.log(arr); // ["悟空", "八戒", "沙和尚"] console.log(新长度); // 3
pop ():拆最后一节车厢,返回拆掉的货:
▼javascript复制代码var 拆掉的 = arr.pop(); // 拆掉沙和尚 console.log(arr); // ["悟空", "八戒"] console.log(拆掉的); // "沙和尚"
unshift ()/shift ():车头加 / 拆车厢,用法和 push/pop 对应:
▼javascript复制代码arr.unshift("唐僧"); // 车头加唐僧→["唐僧", "悟空", "八戒"] var 拆车头 = arr.shift(); // 拆掉唐僧→返回"唐僧"
forEach ():自动查车厢(IE8 及以下不支持,老浏览器慎用):
▼javascript复制代码arr.forEach(function(货, 车厢号, 整列火车) { console.log("车厢" + 车厢号 + ":" + 货); // 自动遍历每节 });
slice ():剪车厢(不破坏原火车,剪下来的装新火车):
▼javascript复制代码var arr = ["悟空", "八戒", "沙和尚", "唐僧"]; var 新火车 = arr.slice(1, 3); // 剪1-3节(不含3)→["八戒", "沙和尚"] var 从第3节开始剪 = arr.slice(3); // ["唐僧"] var 从倒数第2节剪 = arr.slice(1, -2); // 倒数第2节是沙和尚,剪1到沙和尚前→["八戒"]
splice ():暴力拆 / 加车厢(直接改原火车!):
▼javascript复制代码var arr = ["悟空", "八戒", "沙和尚", "唐僧"]; var 拆掉的 = arr.splice(2, 1); // 从第2节开始,拆1节→拆掉沙和尚 arr.splice(1, 0, "牛魔王"); // 从第1节开始,拆0节,加牛魔王→["悟空", "牛魔王", "八戒", "唐僧"]
splice ():暴力拆 / 加车厢(直接改原火车!):
▼javascript复制代码var arr = ["悟空", "八戒", "沙和尚", "唐僧"]; var 拆掉的 = arr.splice(2, 1); // 从第2节开始,拆1节→拆掉沙和尚 arr.splice(1, 0, "牛魔王"); // 从第1节开始,拆0节,加牛魔王→["悟空", "牛魔王", "八戒", "唐僧"]
concat ():两列火车合并(不破坏原火车)
▼javascript复制代码var 取经队 = ["悟空", "八戒"]; var 妖怪队 = ["白骨精", "蜘蛛精"]; var 大杂烩 = 取经队.concat(妖怪队); // 合并→["悟空", "八戒", "白骨精", "蜘蛛精"]
join ():火车变字符串(车厢用指定符号连起来):
▼javascript复制代码var arr = ["悟空", "八戒", "沙和尚"]; console.log(arr.join("&")); // 悟空&八戒&沙和尚(默认用逗号)
reverse ():火车掉头(直接改原火车):
▼javascript复制代码arr.reverse(); // 变成["沙和尚", "八戒", "悟空"]
sort ():火车排序(默认按 Unicode 排,数字排序要加规则):
▼javascript复制代码var 字母车 = ["b", "a", "c"]; 字母车.sort(); // 正常排序→["a", "b", "c"] var 数字车 = [1, 11, 3]; 数字车.sort(); // 坑!按Unicode排→[1, 11, 3] 数字车.sort(function(a, b) { return a - b; }); // 升序→[1, 3, 11] 数字车.sort(function(a, b) { return b - a; }); // 降序→[11, 3, 1]
专业版解析(带核心代码)
数组是 JS 的有序集合对象,用于存储多个数据,核心特性、代码及解析如下:
- 概述:数组属于引用类型,
typeof检测返回object;支持不同类型元素,但建议存储同类型数据以提升可读性和性能;元素通过索引(0 开始)访问。 - 创建方式:
▼javascript复制代码// 1. 构造函数式(可动态添加元素) var arr1 = new Array(); arr1[0] = 1; arr1[1] = "2"; // 允许不同类型 // 2. 字面量式(简洁高效,开发首选) var arr2 = [1, 2, 3]; // 同类型数组 var arr3 = [1, "2", true]; // 混合类型数组
遍历方式:
- for 循环(兼容所有浏览器):
▼javascript复制代码var arr = [1, 2, 3]; for (var i = 0; i < arr.length; i++) { console.log(arr[i]); // 依次输出1、2、3 }
forEach ()(IE8 及以下不兼容):回调函数接收三个参数(当前元素、索引、原数组):
▼javascript复制代码arr.forEach(function(value, index, array) { console.log(value, index, array); });
- 核心属性:
constructor:返回数组构造函数(function Array());length:返回 / 设置数组长度,可手动修改(如arr.length = 0清空数组)。 常用方法解析:
| 方法 | 功能描述 | 核心代码示例 |
|---|---|---|
| push (元素) | 尾部添加元素,返回新长度 | var len = [1,2].push(3); // len=3,数组变为[1,2,3] |
| pop() | 尾部删除元素,返回删除元素 | var del = [1,2,3].pop(); // del=3,数组变为[1,2] |
| unshift (元素) | 头部添加元素,返回新长度 | var len = [1,2].unshift(0); // len=3,数组变为[0,1,2] |
| shift() | 头部删除元素,返回删除元素 | var del = [0,1,2].shift(); // del=0,数组变为[1,2] |
| slice(start, end) | 截取元素(不修改原数组),start 含、end 不含,支持负数(从后数) | [1,2,3,4].slice(1,3); // [2,3];[1,2,3].slice(1,-1); // [2] |
| splice (start, num, 新元素) | 修改原数组,start 起始索引,num 删除个数,后续为添加元素 | [1,2,3].splice(1,1,4); // 删除2,添加4→[1,4,3] |
| concat (数组 / 元素) | 合并数组 / 元素,返回新数组 | [1,2].concat([3,4], 5); // [1,2,3,4,5] |
| join (分隔符) | 数组转字符串,默认分隔符为逗号 | [1,2,3].join("-"); // "1-2-3" |
| reverse() | 反转数组(修改原数组) | [1,2,3].reverse(); // [3,2,1] |
| sort (回调) | 排序(修改原数组),默认按 Unicode 排序,数字排序需传回调(a-b 升序,b-a 降序) | [3,1,2].sort((a,b)=>a-b); // [1,2,3] |
二、函数对象:JS 里的 “百变戏精”
梗版解析(碎碎念 + 代码穿插)
- 函数对象 = 戏精!既能自己干活,还能通过 call/apply “换老板”(改 this 指向)。 call ()= 穿西装上班,参数一个个递:
▼javascript复制代码function 喊老板() { console.log("老板是:" + this.name); } var 张老板 = { name: "张三" }; var 李老板 = { name: "李四" }; 喊老板.call(张老板); // 换张老板→"老板是:张三" 喊老板.call(李老板, 1, 2); // 还能递参数→"老板是:李四"
apply ()= 穿休闲装上班,参数打包成数组递:
▼javascript复制代码喊老板.apply(张老板); // 效果和call一样→"老板是:张三" 喊老板.apply(李老板, [1,2]); // 参数用数组包起来
this 指向 = 戏精的老板,四套剧本:
▼javascript复制代码// 剧本1:函数调用→老板是window function 剧本1() { console.log(this); } 剧本1(); // 输出window // 剧本2:方法调用→老板是调用对象 var obj = { 方法: 剧本1 }; obj.方法(); // 输出obj // 剧本3:构造函数调用→老板是新角色(新对象) function 角色() { console.log(this); } new 角色(); // 输出新创建的角色对象 // 剧本4:call/apply调用→老板是指定对象(上面的张老板/李老板)
arguments = 戏精的 “道具箱”:不管有没有提前说,递过来的道具全在里面:
▼javascript复制代码function 表演() { console.log("第一个道具:" + arguments[0]); // 拿第一个道具 console.log("道具总数:" + arguments.length); // 查道具数量 console.log("当前戏名:" + arguments.callee.name); // 查自己的戏名 } 表演("金箍棒", "紧箍咒"); // 第一个道具:金箍棒;道具总数:2;当前戏名:表演
▼javascript复制代码function 表演() { console.log("第一个道具:" + arguments[0]); // 拿第一个道具 console.log("道具总数:" + arguments.length); // 查道具数量 console.log("当前戏名:" + arguments.callee.name); // 查自己的戏名 } 表演("金箍棒", "紧箍咒"); // 第一个道具:金箍棒;道具总数:2;当前戏名:表演
专业版解析(带核心代码)
函数是 JS 的一等公民,作为对象拥有方法(call/apply)和隐含参数(this/arguments),核心解析如下:
- call () 与 apply ():
- 共同点:调用函数,手动指定 this 指向(第一个参数为 this 指向的对象);
- 区别:参数传递方式不同,call () 后续为单个参数,apply () 后续为参数数组;
- 核心代码:
▼javascript复制代码function fun(a, b) { console.log(this, a, b); } var obj = { name: "obj" }; fun.call(obj, 1, 2); // this=obj,输出obj 1 2 fun.apply(obj, [1, 2]); // this=obj,输出obj 1 2
- this 指向规则:
- 函数调用(
fun()):this → window(非严格模式); - 方法调用(
obj.fun()):this → 调用方法的对象(obj); - 构造函数调用(
new fun()):this → 新创建的实例对象; - call/apply 调用(
fun.call(obj)):this → 第一个参数(obj)。
- 函数调用(
- arguments 对象:
- 类数组对象,存储函数实参,支持索引访问(
arguments[0])和 length 属性; - 含 callee 属性,指向当前执行的函数(可用于匿名函数递归);
- 核心代码:
- 类数组对象,存储函数实参,支持索引访问(
▼javascript复制代码function sum() { var total = 0; for (var i = 0; i < arguments.length; i++) { total += arguments[i]; // 遍历所有实参求和 } return total; } console.log(sum(1, 2, 3)); // 6(无需定义形参即可使用实参)
不懂再解析
再解释
第一步:先搞懂 this 到底是啥(用最简单的例子)
写一个函数,让它打印自己的 “老板”(this):
▼javascript复制代码function whoAmI() { console.log("我现在的老板是:", this); }
现在调用它,看看 “老板” 是谁:
▼javascript复制代码whoAmI(); // 直接调用函数
你会看到输出 我现在的老板是:Window(浏览器里的全局对象,就当是 “大老板”)。
第二步:给函数找个 “小老板”(对象调用函数)
创建一个对象,让这个函数成为对象的 “员工”:
▼javascript复制代码const boss1 = { name: "王总", ask: whoAmI // 让whoAmI成为boss1的方法 }; boss1.ask(); // 让boss1调用这个函数
这时候输出 我现在的老板是:{name: "王总", ask: ...},说明 this 变成了 boss1(谁调用,this 就指向谁)。
第三步:用 call 给函数 “换老板”
再创建一个新老板,用 call 让函数临时为新老板工作:
▼javascript复制代码const boss2 = { name: "李总" }; whoAmI.call(boss2); // 用call强制换老板
输出 我现在的老板是:{name: "李总"},这就是 call 的作用:不管函数原来属于谁,强制让它认新老板。
第四步:call 和 apply 的区别(传参数)
给函数加个功能:除了报老板,还要报今天的业绩:
▼javascript复制代码function reportWork(业绩1, 业绩2) { console.log(`${this.name}的员工汇报:业绩1=${业绩1},业绩2=${业绩2}`); }
用 call 传参数(一个个传):
▼javascript复制代码reportWork.call(boss1, 100, 200); // 输出“王总的员工汇报:业绩1=100,业绩2=200”
用 apply 传参数(放数组里传):
▼javascript复制代码reportWork.apply(boss2, [300, 400]); // 输出“李总的员工汇报:业绩1=300,业绩2=400”
区别就这么简单:call 后面直接跟参数,apply 后面跟一个参数数组。
第五步:arguments 是 “万能参数袋”
写一个 “求和函数”,不管别人传几个数字,都能加起来:
▼javascript复制代码function addAll() { let total = 0; // 用arguments拿到所有传进来的数字,一个个加 for (let i = 0; i < arguments.length; i++) { total = total + arguments[i]; } console.log("总和是:", total); }
试试传不同数量的参数:
▼javascript复制代码addAll(1, 2); // 总和是:3 addAll(10, 20, 30, 40); // 总和是:100 addAll(5); // 总和是:5
如果没有 arguments,你得提前知道用户要传几个数,比如 function addAll(a, b, c) { ... },但这样用户传 4 个数就处理不了了。arguments 解决的就是这个 “不确定参数数量” 的问题。
现在再回头看核心点
this:函数执行时,到底在为哪个对象工作(老板是谁)。call/apply:手动指定函数的老板,顺便传参数让函数执行(区别只是传参方式)。arguments:函数内部自动生成的 “参数列表”,不管传多少参数都能拿到。
为什么存在它
场景 1:为什么需要 this?
想象你是一家公司的员工(函数),你的工作是 “汇报今天的销售额”。
- 如果你在 “A 部门” 上班(函数被 A 对象调用),你应该汇报 A 部门的销售额;
- 如果你被临时调到 “B 部门”(函数被 B 对象调用),你应该汇报 B 部门的销售额。
这里的 “部门” 就是 this,它让函数知道 “自己当前为谁工作”,不用写死到底汇报哪个部门的数据。
比如:
▼javascript复制代码// 员工(函数):汇报当前部门的销售额 function reportSales() { console.log(`今天销售额:${this.sales}元`); } // A部门 const departmentA = { sales: 1000, report: reportSales }; // B部门 const departmentB = { sales: 2000, report: reportSales }; departmentA.report(); // 为A工作 → 输出“今天销售额:1000元” departmentB.report(); // 为B工作 → 输出“今天销售额:2000元”
场景 2:为什么需要 call/apply?
还是上面的例子:假设你(reportSales 函数)本来是 A 部门的,但某天老板突然说 “你临时去 C 部门帮忙汇报一下”。
这时候 call/apply 就是 “临时调令”,让你强制切换到 C 部门工作。
▼javascript复制代码const departmentC = { sales: 3000 }; // 用call强制让函数为C部门工作 reportSales.call(departmentC); // 输出“今天销售额:3000元”
没有 call/apply,函数只能固定为 “自己所在的部门” 工作,没法临时调配,灵活性太差了。
场景 3:为什么需要 arguments?
想象你是一个 “计算器”(函数),功能是 “把所有输入的数字加起来”。
但用户可能输入 2 个数字,也可能输入 10 个数字 —— 你总不能提前知道用户要输入几个吧?
arguments 就是 “不管用户输入多少,都能把所有数字装起来” 的盒子。
比如例子中的 sum 函数:
▼javascript复制代码function sum() { let total = 0; // 不管传几个数字,都从arguments里拿出来加起来 for (let i = 0; i < arguments.length; i++) { total += arguments[i]; } return total; } sum(1, 2); // 3(2个数字) sum(1, 2, 3, 4); // 10(4个数字)
如果没有 arguments,你得提前定义无数个形参(sum(a,b,c,d,e...)),根本不现实!
三、Date 对象:JS 里的 “时间记录仪”
梗版解析(碎碎念 + 代码穿插)
- Date 对象 = 随身记录仪!专门记录时间,new 一下就抓当前时间:
▼javascript复制代码var 现在时间 = new Date(); console.log(现在时间); // 输出当前完整时间(如Fri Sep 01 2023 10:00:00 GMT+0800)
时间拆解 = 拆记录仪数据,想拿年、月、日直接调方法:
▼javascript复制代码var 时间 = new Date(); console.log("年份:" + 时间.getFullYear()); // 四位年份→2023 console.log("月份:" + (时间.getMonth() + 1)); // 月份0-11,要加1→9(9月) console.log("日期:" + 时间.getDate()); // 1-31→1 console.log("小时:" + 时间.getHours()); // 0-23→10 console.log("分钟:" + 时间.getMinutes()); // 0-59→0 console.log("秒:" + 时间.getSeconds()); // 0-59→0 console.log("毫秒:" + 时间.getMilliseconds()); // 0-999→123
- 注意:月份是 0 开始的!0=1 月,11=12 月,别搞混了,不然会把 10 月当成 9 月!
专业版解析(带核心代码)
Date 对象用于表示时间,支持获取和操作日期时间,核心解析如下:
- 创建方式:
new Date():默认封装当前系统时间;new Date(时间字符串):解析指定时间(如new Date("2023-09-01"));new Date(年, 月, 日, 时, 分, 秒):指定时间(月份 0-11)。
- 核心方法(获取时间分量):
▼javascript复制代码var date = new Date(); date.getFullYear(); // 获取四位年份(如2023) date.getMonth(); // 获取月份(0-11,需+1才是实际月份) date.getDate(); // 获取日期(1-31) date.getHours(); // 获取小时(0-23) date.getMinutes(); // 获取分钟(0-59) date.getSeconds(); // 获取秒(0-59) date.getMilliseconds(); // 获取毫秒(0-999)
- 注意事项:月份索引从 0 开始,需手动 + 1 才能匹配实际月份;日期方法返回的是本地时间(可通过
getUTCxxx()方法获取 UTC 时间)。
四、Math 对象:JS 里的 “随身计算器”(补全)
梗版解析(碎碎念 + 代码穿插)
- Math 对象 = 不用充电的随身计算器!跟别的对象不一样,它是 “工具人”,不用 new,直接喊名字用,里面全是数学干货:
- 固定值:π 和 E 直接拿,不用自己记:
▼javascript复制代码console.log("π≈" + Math.PI); // 3.14159...(算圆面积必备) console.log("E≈" + Math.E); // 2.718...(高数党懂的都懂)
正数运算:四舍五入、取整全拿捏:
▼javascript复制代码console.log(Math.abs(1)); // 绝对值→1(正数不变) console.log(Math.ceil(1.1)); // 向上取整→2(哪怕小数点后是1也进1,像极了老板凑整扣工资) console.log(Math.floor(1.99)); // 向下取整→1(小数点后全砍,像极了给你发奖金时抹零) console.log(Math.round(1.4)); // 四舍五入→1(1.5及以上才进,公正!)
负数运算:别搞反!越负越离谱:
▼javascript复制代码console.log(Math.abs(-1)); // 绝对值→1(负负得正) console.log(Math.ceil(-1.1)); // 向上取整→-1(往大的数靠,-1比-1.1大) console.log(Math.floor(-1.99)); // 向下取整→-2(往小的数靠,-2比-1.99小) console.log(Math.round(-1.4)); // 四舍五入→-1(注意:-1.5会舍成-1,不是-2!)
随机数:抽奖、发红包必备:
▼javascript复制代码// 生成0-10的随机数(含0和10) console.log(Math.round(Math.random() * 10)); // 生成1-10的随机数(不含0,适合抽1-10等奖) console.log(Math.round(Math.random() * (10 - 1) + 1));
高级运算:幂和平方根,不用手算:
▼javascript复制代码console.log(Math.pow(12, 3)); // 12的3次方→1728(算体积用) console.log(Math.sqrt(4)); // 4的平方根→2(算边长用)
专业版解析(带核心代码)
Math 是 JS 的数学工具类,非构造函数,无需实例化,直接通过Math.属性/方法调用,核心解析如下:
- 核心属性:
Math.PI:圆周率(约 3.141592653589793);Math.E:自然常数(约 2.718281828459045)。
- 常用方法
| 方法 | 功能描述 | 核心代码示例 | 补充说明 | 高频扩展用法 | 易错点提醒 |
| Math.abs(x) | 计算 x 的绝对值 | Math.abs(-5); // 5Math.abs(2.3); // 2.3 | 1. 支持整数、浮点数、负数;2. 非数字参数:可转数字则计算(如 '5'→5),不可转则返回 NaN(如 'abc'→NaN) | - | 传入 undefined 会返回 NaN,传入 null 会返回 0(null 转数字为 0) |
| Math.ceil(x) | 向上取整(小数位非 0 则进 1) | Math.ceil(2.1); // 3Math.ceil(2.0); // 2 | 对负数生效:Math.ceil(-2.1)→-2(往更大数靠拢) | - | 勿混淆负数逻辑:Math.ceil(-2.9) 结果是 -2 而非 -3 |
| Math.floor(x) | 向下取整(舍弃小数位) | Math.floor(2.9); // 2Math.floor(3.0); // 3 | 对负数生效:Math.floor(-2.1)→-3(往更小数靠拢) | 结合 Math.random() 生成 [min, max] 随机整数:Math.floor(Math.random()*(max-min+1))+min | 勿混淆负数逻辑:Math.floor(-2.1) 结果是 -3 而非 -2 |
| Math.round(x) | 四舍五入取整(x≥0.5 进 1,x<0.5 舍) | Math.round(2.4); // 2Math.round(2.5); // 2 | 1. 负数规则:Math.round(-2.5)→-2(距偶数更近);2. .5 特殊处理:向最近偶数取整 | 保留 n 位小数:Math.round(num * Math.pow(10, n)) / Math.pow(10, n) | 小数位为 0.5 时不单纯进 1:Math.round(3.5)→4、Math.round(4.5)→4 |
| Math.random() | 生成 0(含)~1(不含)的随机浮点数 | Math.random(); // 0.123... | 1. 伪随机数(不适合加密,加密用 window.crypto.getRandomValues());2. 永远不返回 1 | 生成 1~10 随机整数:Math.floor(Math.random()*10)+1 | 误判返回范围:不会返回 1,需包含 1 需用 (max-min+1) 公式 |
| Math.pow(x,y) | 计算 x 的 y 次幂 | Math.pow(2, 3); // 8Math.pow(4, 0.5); // 2 | 支持小数次幂(如 0.5 等价于开平方根) | 计算 n 次方根:Math.pow(8, 1/3)→2(8 的立方根) | 传入负数底数 + 非整数指数:返回 NaN(如 Math.pow(-4, 0.5)→NaN) |
| Math.sqrt(x) | 计算 x 的平方根(x≥0) | Math.sqrt(9); // 3Math.sqrt(16); // 4 | 仅支持非负数,负数返回 NaN | - | 传入负数直接返回 NaN,需提前判断 x 正负 |
- 注意事项:
- 负数取整时,
ceil()向更大的数靠拢(如-1.1→-1),floor()向更小的数靠拢(如-1.1→-2); Math.random()生成的是浮点数,需配合round()/floor()转换为整数,指定范围公式:Math.round(Math.random()*(max-min)+min)(含 max 和 min)。
- 负数取整时,
五、String 对象:JS 里的 “文字魔术师”
梗版解析(碎碎念 + 代码穿插)
- String 对象 = 文字魔术师!能把普通字符串玩出花,还能通过包装类把 “字符串字面量” 变成对象(但平时不用,纯属多此一举):
▼javascript复制代码// 普通字符串(字面量) var str1 = "Hello,World!"; // 字符串对象(包装类,不推荐用) var str2 = new String("Hello,World!");
字符串属性 = 魔术师的道具清单:
▼javascript复制代码var str = "Hello,World!"; console.log(str.constructor); // 看魔术原理→function String(){} console.log(str.length); // 看文字长度→12(逗号和感叹号都算!)
字符串方法 = 魔术招式(重点!):
- charAt ():按位置抽字符:
▼javascript复制代码console.log(str.charAt(1)); // 抽第1位(0开始)→"e"
charCodeAt ():抽字符的 “身份证号”(Unicode 编码):
▼javascript复制代码console.log(str.charCodeAt(1)); // "e"的编码→101
concat ():字符串拼接(跟用 + 号一样,纯属多此一举但要会):
▼javascript复制代码console.log(str.concat(" 你好!", " 世界!")); // "Hello,World! 你好! 世界!"
indexOf ()/lastIndexOf ():找字符位置(前者从左找,后者从右找)
▼javascript复制代码console.log(str.indexOf("o")); // 第一个"o"在第4位→4 console.log(str.lastIndexOf("o")); // 最后一个"o"在第7位→7
slice ():切字符串(不破坏原串,支持负数,从后数)
▼javascript复制代码console.log(str.slice(1, 4)); // 切1-4位(不含4)→"ell" console.log(str.slice(1, -1)); // 切1到倒数第1位→"ello,World"
substring ():切字符串(跟 slice 像,但不支持负数,参数会自动交换):
▼javascript复制代码console.log(str.substring(4, 1)); // 参数反了,自动交换→"ell"(同slice(1,4)) console.log(str.substring(1, -1)); // 负数当0→"H"
substr ():按长度切字符串(第一个参数是起始位置,第二个是长度):
▼javascript复制代码console.log(str.substr(6, 5)); // 从第6位开始,切5个→"World"
split ():字符串变数组(按指定符号拆分):
▼javascript复制代码console.log(str.split(",")); // 按逗号拆→["Hello", "World!"]
toUpperCase ()/toLowerCase ():大小写转换(变魔术必备):
▼javascript复制代码console.log(str.toUpperCase()); // 全大写→"HELLO,WORLD!" console.log(str.toLowerCase()); // 全小写→"hello,world!"
专业版解析(带核心代码)
String 对象用于处理字符串,JS 通过包装类自动将字符串字面量转换为对象以调用方法,核心解析如下:
- 概述:
- 包装类:
String()可将字符串字面量转为对象(如var str = new String("abc")),但实际开发中直接使用字面量(var str = "abc"),避免比较异常; typeof检测字符串字面量返回string,检测 String 对象返回object。
- 包装类:
- 核心属性:
constructor:返回 String 构造函数(function String());length:返回字符串长度(空格、标点均算字符)。
- 常用方法解析:
| 方法名 | 功能描述 | 核心代码示例及结果 | 注意事项 |
| charAt(index) | 获取字符串中索引 index 处的字符(索引从 0 开始) | "abc".charAt(1); // 结果:"b" "abc".charAt(5); // 结果:""(索引越界返回空串) | 若 index 超出字符串长度(或为负数),返回空字符串而非报错 |
| charCodeAt(index) | 获取字符串中索引 index 处字符的 Unicode 编码(十进制) | "abc".charCodeAt(1); // 结果:98("b" 的 Unicode 编码) "A".charCodeAt(0); // 65 | 常用于字符类型判断(如数字:48-57、大写字母:65-90、小写字母:97-122) |
| concat(str1, str2) | 拼接多个字符串,返回新字符串(功能与 + 运算符一致) | "a".concat("b", "c"); // 结果:"abc" "Hi ".concat("John", "!"); // "Hi John!" | 拼接大量字符串时,性能与 + 相近;推荐优先使用 + 或模板字符串(更简洁) |
| indexOf(str, start) | 从索引 start(默认 0)开始,查找子串 str 第一次出现的索引;未找到返回 -1 | "abac".indexOf("a"); // 0 "abac".indexOf("a", 1); // 2 "abac".indexOf("x"); // -1 | start 可省略(默认从 0 开始);区分大小写(如 "Abc".indexOf("a") → -1) |
| lastIndexOf(str) | 从字符串末尾往前查找子串 str 第一次出现的索引;未找到返回 -1 | "abac".lastIndexOf("a"); // 2 "abcabc".lastIndexOf("abc"); // 3 | 同样区分大小写;常用于获取最后一个目标子串的位置(如文件扩展名) |
| slice(start, end) | 截取字符串(含 start,不含 end);支持负数索引(从末尾计数:-1 为最后一位) | "abcde".slice(1, 3); // "bc" "abcde".slice(1, -1); // "bcd" "abcde".slice(-3); // "cde" | 若 end ≤ start,返回空字符串;负数索引灵活,适合 “从末尾截取” 场景 |
| substring(start, end) | 截取字符串(含 start,不含 end);不支持负数(按 0 处理),自动交换参数 | "abcde".substring(3, 1); // "bc"(自动交换为 1-3) "abcde".substring(-2, 3); // "abc"(负数按 0 算) | 不推荐用于需要负数索引的场景;优先选择 slice(功能更灵活) |
| substr(start, len) | 从索引 start 开始,截取长度为 len 的字符;start 支持负数 | "abcde".substr(1, 3); // "bcd" "abcde".substr(-2, 2); // "de" "abcde".substr(3); // "de" | 部分浏览器(如旧版 IE)对负数 start 处理不一致,推荐用 slice 替代 |
| split(sep) | 按分隔符 sep(字符串 / 正则)拆分字符串为数组;sep 为 "" 时拆分为单个字符 | "a,b,c".split(","); // ["a","b","c"] "hello world".split(" "); // ["hello","world"] "abc".split(""); // ["a","b","c"] | 若 sep 未找到,返回仅含原字符串的数组;支持正则(如 split(/[,; ]/) 多分隔符) |
| toUpperCase() | 将字符串转为大写形式,返回新字符串 | "abc".toUpperCase(); // "ABC" "aBc123".toUpperCase(); // "ABC123" | 仅对字母生效,数字、符号不变;常用于统一输入格式(如用户名、搜索关键词) |
| toLowerCase() | 将字符串转为小写形式,返回新字符串 | "ABC".toLowerCase(); // "abc" "HeLLo".toLowerCase(); // "hello" | 与 toUpperCase() 对应,适合不区分大小写的判断场景(如密码验证) |
三、关键方法差异对比
1. 截取方法对比(slice vs substring vs substr)
| 维度 | slice(start, end) | substring(start, end) | substr(start, len) |
| 参数含义 | 开始索引 / 结束索引 | 开始索引 / 结束索引 | 开始索引 / 截取长度 |
| 负数处理 | 支持(从末尾计数) | 不支持(按 0 处理) | start 支持负数,len 不支持(负数返回空串) |
| 参数顺序 | 不自动交换(start > end 返回空串) | 自动交换(保证 start ≤ end) | 无顺序问题(len 为长度) |
| 推荐场景 | 灵活截取(尤其是需要负数索引) | 简单正向截取(无负数需求) | 已知截取长度的场景(谨慎使用,兼容性略差) |
2. 查找方法对比(indexOf vs lastIndexOf)
| 维度 | indexOf(str, start) | lastIndexOf(str) |
| 查找方向 | 从左往右(正向) | 从右往左(反向) |
| 常用场景 | 查找子串第一次出现的位置 | 查找子串最后一次出现的位置(如文件扩展名、最后一个分隔符) |
| 示例 | "abcabc".indexOf("abc") → 0 | "abcabc".lastIndexOf("abc") → 3 |
六、RegExp 对象:JS 里的 “字符串安检员”
梗版解析(碎碎念 + 代码穿插)
- RegExp 对象 = 机场安检员!专门查字符串是否符合规则(比如手机号、邮箱格式),还能把违规内容揪出来。
- 创建安检员两种姿势:
▼javascript复制代码// 姿势1:new RegExp(正规流程,麻烦) var 安检员1 = new RegExp("a", "i"); // 查是否有"a",忽略大小写(i模式) // 姿势2:字面量(简洁,推荐!) var 安检员2 = /a/i; // 效果同上,斜杠里是规则,后面是模式
- 模式开关:安检员的特殊技能:
- i:忽略大小写(查 a 和 A 都算);
- g:全局模式(查所有符合规则的,不是只查第一个);
- ig:又忽略大小写又全局查。
- 基础规则:教安检员认东西:
- 或规则(|):查 a 或 b 或 c:
/a|b|c/; - 范围规则([]):查任意字母:
/[A-z]/(比写 a|b|c... 省事多了);- {a-z]:小写字母;{A-Z]:大写字母;{0-9]:数字;
- 排除规则([^]):查除了数字以外的:
/[^0-9]/(^ 在 [] 里是 “排除”); - 组合规则:查 abc、adc、aec:
/a[bde]c/(中间只能是 b、d、e)。
- 或规则(|):查 a 或 b 或 c:
▼javascript复制代码var str = "Abc123"; console.log(/[A-z]/.test(str)); // 查是否有字母→true console.log(/[^0-9]/.test(str)); // 查是否有非数字→true
量词规则:查出现次数(安检员查重复物品):
- {n}:正好 n 次(查 3 个 b:
/b{3}/); - {m,}:至少 m 次(查 2 个及以上 b:
/b{2,}/); - {m,n}:m-n 次(查 1-3 个 b:
/b{1,3}/); - +:至少 1 次(相当于 {1,},查 1 个及以上 b:
/b+/); - *:0 或多次(相当于 {0,},查 0 个或多个 b:
/b*/); - ?:0 或 1 次(相当于 {0,1},查 0 个或 1 个 b:
/b?/)。
▼javascript复制代码var str = "abbc"; console.log(/ab{2}c/.test(str)); // 查a后接2个b再接c→true
高阶规则:查开头、结尾和特殊字符:
- ^:开头(查是否以 a 开头:
/^a/); - :结尾(查是否以结尾:/`);
- 转义字符:查。或 \(需加 \,比如查.:
/\./,用 new RegExp 要写new RegExp("\\.")); - 快捷符号:
- \w:任意字母、数字、(相当于 {A-z0-9]);
- \d:任意数字(相当于 {0-9]);
- \s:空格;
- \b:单词边界(查完整单词,比如查 “child” 不查 “children”:
/\bchild\b/)。
▼javascript复制代码// 去除字符串前后空格(实用!) var str = " hello child "; var 去空格安检员 = /^\s*|\s*$/g; // 查开头/结尾的空格(任意个) console.log(str.replace(去空格安检员, "")); // "hello child"
-
▼javascript复制代码
console.log(str.replace(去空格安检员, "")); // "hello child" -
安检员技能(字符串方法传正则):
- split ():按规则拆分(比如拆数字和字母:
"1a2b".split(/[A-z]/)→ {"1","2"]); - search ():找第一个符合规则的位置(查 abc:
"hello abc".search(/a[b]c/)→ 6); - match ():把所有符合规则的揪出来(查所有字母:
"1a2A".match(/[a-z]/ig)→ {"a","A"]); - replace ():替换符合规则的内容(把字母换成 @:
"1a2b".replace(/[A-z]/g, "@")→ "1@2@")。
- split ():按规则拆分(比如拆数字和字母:
-
实战案例
▼javascript复制代码// 查手机号(1开头,3-9中间,后面9个数字) var 手机号 = "15131494600"; var 手机号安检员 = /^1[3-9][0-9]{9}$/; console.log(手机号安检员.test(手机号)); // true // 查邮箱(比如abc.def@163.com) var 邮箱 = "abc.def@163.com"; var 邮箱安检员 = /^\w{3,}(\.\w+)*@[A-z0-9]+(\.[A-z]{2,5}){1,2}$/; console.log(邮箱安检员.test(邮箱)); // true
专业版解析(带核心代码)
RegExp(正则表达式)用于定义字符串规则,可检查字符串是否匹配、提取 / 替换匹配内容,核心解析如下:
- 概述:正则表达式是对象,
typeof检测返回object,用于字符串的模式匹配。 - 创建方式:
- 构造函数式:
new RegExp("规则", "模式")(规则需转义特殊字符,如new RegExp("\\.")匹配.); - 字面量式:
/规则/模式(简洁高效,无需双重转义,开发首选)。
- 构造函数式:
