字符串


字符串就是零个或多个排在一起的字符,放在单引号或双引号之中

'itbaizhan'
"itbaizhan"

单引号字符串的内部,可以使用双引号。双引号字符串的内部,可以使用单引号

'key = "value"'
"It's a long itbaizhan"

如果要在单引号字符串的内部,使用单引号,就必须在内部的单引号前面加上反斜杠,用来转义。双引号字符串内部使用双引号,也是如此

'Did she say \'Hello\'?'
// "Did she say 'Hello'?"
"Did she say \"Hello\"?"
// "Did she say "Hello"?"

温馨提示
字符串默认只能写在一行内,分成多行将会报错

如果长字符串必须分成多行,可以在每一行的尾部使用反斜杠

var longString = 'Long \
long \
string';
longString
// "Long long long string"

转义
反斜杠(\)在字符串内有特殊含义,用来表示一些特殊字符,所以又称为转义符

\0 :null(\u0000)
\b :后退键(\u0008)
\f :换页符(\u000C)
\n :换行符(\u000A)
\r :回车键(\u000D)
\t :制表符(\u0009)
\v :垂直制表符(\u000B)
’ :单引号(\u0027)
" :双引号(\u0022)
\ :反斜杠(\u005C)

length 属性
length属性返回字符串的长度,该属性也是无法改变的

var s = 'itbaizhan';
s.length // 9

字符串转码


Base64转码
所谓 Base64 就是一种编码方法,可以将任意值转成 0~9、A~Z、a-z、+和/这64个字符组成的可打印字符。使用它的主要目的,不是为了加密,而是为了不出现特殊字符,简化程序的处理
JavaScript 原生提供两个 Base64 相关的方法

btoa():任意值转为 Base64 编码
atob():Base64 编码转为原来的值

var string = 'Hello World!';
btoa(string) // "SGVsbG8gV29ybGQh"
atob('SGVsbG8gV29ybGQh') // "Hello World!"

温馨提示
中文是不可以进行处理的

如果非要处理中文,需要在增加两个方法

encodeURIComponent()
decodeURIComponent()
function b64Encode(str) {return btoa(encodeURIComponent(str));
}
function b64Decode(str) {return decodeURIComponent(atob(str));
}
b64Encode('你好') //"JUU0JUJEJUEwJUU1JUE1JUJE"
b64Decode('JUU0JUJEJUEwJUU1JUE1JUJE') // "你好"

字符串方法_charAt()


charAt 方法返回指定位置的字符,参数是从 0 开始编号的

var s = new String('itbaizhan');
s.charAt(1) // "t"
s.charAt(s.length - 1) // "n"

如果参数为负数,或大于等于字符串的长度,charAt 返回空字符串

'itbaizhan'.charAt(-1) // ""
'itbaizhan'.charAt(9) // ""

字符串方法_concat()

concat 方法用于连接两个字符串,返回一个新字符串,不改变原字符串

var s1 = 'itbaizhan';
var s2 = 'sxt';
s1.concat(s2) // "itbaizhansxt"
s1 // "itbaizhan"

该方法可以接受多个参数

'sxt'.concat('itbaizhan', 'bjsxt') //"sxtitbaizhanbjsxt"

如果参数不是字符串, concat 方法会将其先转为字符串,然后再连接

var one = 1;
var two = 2;
var three = '3';
''.concat(one, two, three) // "123"

字符串方法_slice()

slice 方法用于从原字符串取出子字符串并返回,不改变原字符串。
它的第一个参数是子字符串的开始位置,第二个参数是子字符串的结束位置(不含该位置)

'itbaizhan'.slice(0, 4) // "it"

如果省略第二个参数,则表示子字符串一直到原字符串结束

'itbaizhan'.slice(2) // "baizhan"

如果参数是负值,表示从结尾开始倒数计算的位置,即该负值加上字符串长度

'itbaizhan'.slice(-7) // "baizhan"
'itbaizhan'.slice(0, -7) // "it"
'itbaizhan'.slice(-2, -1) // "a"

如果第一个参数大于第二个参数, slice 方法返回一个空字符串

'itbaizhan'.slice(2, 1) // ""

字符串方法_substring()

substring 方法用于从原字符串取出子字符串并返回,不改变原字符串,跟 slice 方法很相像。它的第一个参数表示子字符串的开始位置,第二个位置表示结束位置(返回结果不含该位置)

'itbaizhan'.substring(0, 2) // "it"

如果省略第二个参数,则表示子字符串一直到原字符串的结束

'itbaizhan'.substring(2) // "baizhan"

如果第一个参数大于第二个参数, substring 方法会自动更换两个参数的位置

'itbaizhan'.substring(9, 2) // "baizhan"
// 等同于
'itbaizhan'.substring(2, 9) // "baizhan"

如果参数是负数, substring 方法会自动将负数转为0

'itbaizhan'.substring(-3) // "itbaizhan"
'itbaizhan'.substring(2, -3) // "it"

由于这些规则违反直觉,因此不建议使用 substring 方法,应该优先使用 slice

字符串方法_substr()

substr 方法用于从原字符串取出子字符串并返回,不改变原字符串,跟 slicesubstring 方法的作用相同
substr 方法的第一个参数是子字符串的开始位置(从0开始计算),第二个参数是子字符串的长度

'itbaizhan'.substr(2, 7); // baizhan

如果省略第二个参数,则表示子字符串一直到原字符串的结束

'itbaizhan'.substr(2) // "baizhan"

如果第一个参数是负数,表示倒数计算的字符位置。如果第二个参数是负数,将被自动转为0,因此会返回空字符串

'itbaizhan'.substr(-7) // "baizhan"
'itbaizhan'.substr(4, -1) // ""

字符串方法_indexOf()/lastIndexOf()

indexOf 方法用于确定一个字符串在另一个字符串中第一次出现的位置,返回结果是匹配开始的位置。如果返回 -1 ,就表示不匹配

'hello world'.indexOf('o') // 4
'itbaizhan'.indexOf('sxt') // -1

indexOf 方法还可以接受第二个参数,表示从该位置开始向后匹配

'hello world'.indexOf('o', 6) // 7

lastIndexOf 方法的用法跟 indexOf 方法一致,主要的区别是 lastIndexOf 从尾部开始匹配, indexOf 则是从头部开始匹配

'itbaizhan'.lastIndexOf('z') // 5

字符串方法_trim()

trim 方法用于去除字符串两端的空格,返回一个新字符串,不改变原字符串

' hello world '.trim()
// "hello world"

该方法去除的不仅是空格,还包括制表符( \t 、 \v )、换行符( \n )和回车符( \r )

'\r\nitbaizhan \t'.trim() // 'itbaizhan'

ES6扩展方法, trimEnd()trimStart() 方法

"   itbaizhan   ".trimEnd(); //   itbaizhan
"   itbaizhan   ".trimStart(); // itbaizhan

字符串方法_toLowerCase()/toUpperCase()

toLowerCase 方法用于将一个字符串全部转为小写, toUpperCase 则是全部转为大写。它们都返回一个新字符串,不改变原字符串

'Hello World'.toLowerCase()
// "hello world"
'Hello World'.toUpperCase()
// "HELLO WORLD"

将字符串首字母变为大写

itbaizhan'.charAt(0).toUpperCase() +
'itbaizhan'.substr(1);

字符串方法_search()/replace()

search 方法确定原字符串是否匹配某个子字符串,返回值为匹配的第一个位置。如果没有找到匹配,则返回 -1

'itbaizhan,sxt'.search('bai') // 2

replace 方法用于替换匹配的子字符串

'sxtbaizhan'.replace('sxt', 'it') //"itbaizhan"

字符串方法_split()

split 方法按照给定规则分割字符串,返回一个由分割出来的子字符串组成的数组

'it|sxt|baizhan'.split('|') // ["it", "sxt","baizhan"]

如果分割规则为空字符串,则返回数组的成员是原字符串的每一个字符。

'a|b|c'.split('') // ["a", "|", "b","|","c"]

如果省略参数,则返回数组的唯一成员就是原字符串

'it|sxt|bz'.split() // [it|sxt|bz]

split 方法还可以接受第二个参数,限定返回数组的最大成员数。

'it|sxt|bz'.split('|', 0) // []
'it|sxt|bz'.split('|', 1) // ["it"]
'it|sxt|bz'.split('|', 2) // ["it", "sxt"]
'it|sxt|bz'.split('|', 3) // ["it", "sxt","bz"]
'it|sxt|bz'.split('|', 4) // ["it", "sxt","bz"]

数组

数组(array)是按次序排列的一组值。每个值的位置都有编号(从0开始),整个数组用方括号表示。

var arr = ['sxt', 'baizhan', 'it'];

两端的方括号是数组的标志。 sxt 是0号位置, baizhan 是1号位置, it 是2号位置。

除了在定义时赋值,数组也可以先定义后赋值。

var arr = [];
arr[0] = 'sxt';
arr[1] = 'baizhan';
arr[2] = 'it';

任何类型的数据,都可以放入数组

var arr = [ 100, [1, 2, 3],false ];

如果数组的元素还是数组,就形成了多维数组

var a = [[1, 2], [3, 4]];
a[0][1] // 2
a[1][1] // 4

数组的本质
本质上,数组属于一种特殊的对象。typeof运算符会返回数组的类型是object

typeof [1, 2, 3] // "object"

length 属性
数组的length属性,返回数组的成员数量

['sxt', 'baizhan', 'it'].length // 3

length属性是可写的。如果人为设置一个小于当前成员个数的值,该数组的成员会自动减少到length设置的值

var arr = ['sxt', 'baizhan', 'it'];
arr.length = 2; // ['sxt', 'baizhan']

清空数组的一个有效方法,就是将length属性设为0

var arr = [ 'sxt', 'baizhan', 'it' ];
arr.length = 0; // []

数组的遍历

数组的遍历可以考虑使用 for 循环或 while 循环

var a = ['sxt', 'baizhan', 'it'];
// for循环
for(var i = 0; i < a.length; i++) {console.log(a[i]);
}
// while循环
var i = 0;
while (i < a.length) {console.log(a[i]);i++;
}

for...in 遍历数组

var a = ['sxt', 'baizhan', 'it'];
for (var i in a) {console.log(a[i]);
}

数组构造函数

数组的空位
当数组的某个位置是空元素,即两个逗号之间没有任何值,我们称该数组存在空位

var a = ['sxt', ,'it'];
a.length // 3  空位也占据位置

温馨提示
如果参数是一个正整数,返回数组的成员都是空位。虽然读取的时候返回 undefined ,但实际上该位置没有任何值。虽然可以取到 length 属性,但是取不到键名

构造函数
Array 是 JavaScript 的原生对象,同时也是一个构造函数,可以用它生成新的数组

var arr = new Array(2);
arr.length // 2
arr // [ empty x 2 ]

如果没有使用 new ,运行结果也是一样的。

var arr = new Array(2);
// 等同于
var arr = Array(2);

不建议使用它生成新数组,直接使用数组字面量是最简约的做法

数组静态方法_Array.isArray()


Array.isArray 方法返回一个布尔值,表示参数是否为数组。它可以弥补typeof 运算符的不足

var arr = ["尚学堂", 100, true];
console.log(typeof arr); // object
var arr = ['sxt', 'baizhan', 'it'];
Array.isArray(arr) // true

数组方法_push()/pop()

push 方法用于在数组的末端添加一个或多个元素,并返回添加新元素后的数组长度。

注意,该方法会改变原数组

var arr = [];
arr.push("尚学堂") // 1
arr.push('itbaizhan') // 2
arr.push(true, {}) // 4
arr // [尚学堂, 'itbaizhan', true, {}]

pop 方法用于删除数组的最后一个元素,并返回该元素。注意,该方法会改变原数组

var arr = ['尚学堂', 'itbaizhan', 'WEB前端'];
arr.pop() // 'WEB前端'
arr // ['尚学堂', 'itbaizhan']

对空数组使用 pop 方法,不会报错,而是返回 undefined

[].pop() // undefined

pushpop 结合使用,就构成了“后进先出”

var arr = [];
arr.push('尚学堂', 'itbaizhan');
arr.push('WEB前端');
arr.pop();
arr // ['尚学堂', 'itbaizhan']

数组方法_shift()/unshift()

shift 方法用于删除数组的第一个元素,并返回该元素。注意,该方法会改变原数组

var arr = ['尚学堂', 'itbaizhan', 'WEB前端'];
arr.shift() // '尚学堂'
arr // ['itbaizhan', 'WEB前端']

shift 方法可以遍历并清空一个数组

var list = [1, 2, 3, 4, 5, 6];
var item;
while (item = list.shift()) {console.log(item);
}
list // []

unshift 方法用于在数组的第一个位置添加元素,并返回添加新元素后的数组长度。注意,该方法会改变原数组

var arr = ['尚学堂', 'itbaizhan', 'WEB前端'];
arr.unshift('baizhan'); // 4
arr // ['baizhan', '尚学堂', 'itbaizhan', 'WEB前端']

unshift 方法可以接受多个参数,这些参数都会添加到目标数组头部

var arr = [ '尚学堂', 'itbaizhan' ];
arr.unshift('WEB前端', 'baizhan') // 4
arr // [ 'WEB前端', 'baizhan', '尚学堂','itbaizhan' ]

数组方法_join()

join 方法以指定参数作为分隔符,将所有数组成员连接为一个字符串返回。如果不提供参数,默认用逗号分隔

var a = [1, 2, 3, 4];
a.join(' ') // '1 2 3 4'
a.join(' | ') // "1 | 2 | 3 | 4"
a.join() // "1,2,3,4"

如果数组成员是 undefinednull 或空位,会被转成空字符串

[undefined, null].join('#')
// '#'
['a',, 'b'].join('-')
// 'a--b'

数组的 join 配合字符串的 split 可以实现数组与字符串的互换

var arr = ["a","b","c"];
var myArr = arr.join("");
console.log(myArr);
console.log(myArr.split(""));

数组方法_concat()

concat 方法用于多个数组的合并。它将新数组的成员,添加到原数组成员的后部,然后返回一个新数组,原数组不变

['hello'].concat(['world'])
// ["hello", "world"]
['hello'].concat(['world'], ['!'])
// ["hello", "world", "!"]

除了数组作为参数, concat 也接受其他类型的值作为参数,添加到目标数组尾部。

[1, 2, 3].concat(4, 5, 6)
// [1, 2, 3, 4, 5, 6]

应用场景
上拉加载,合并数据

数组方法_reverse()

reverse 方法用于颠倒排列数组元素,返回改变后的数组。注意,该方法将改变原数组

var a = ['a', 'b', 'c'];
a.reverse() // ["c", "b", "a"]
a // ["c", "b", "a"]

实现一个字符串反转排列

var str = "hello";
str.split("").reverse().join("")

数组方法_slice()

slice 方法用于提取目标数组的一部分,返回一个新数组,原数组不变

arr.slice(start, end);

它的第一个参数为起始位置(从0开始),第二个参数为终止位置(但该位置的元素本身不包括在内)。如果省略第二个参数,则一直返回到原数组的最后一个成员

var arr = ['尚学堂', 'itbaizhan', '百战程序员'];
arr.slice(0) // ['尚学堂', 'itbaizhan', '百战程序员']
arr.slice(1) // [itbaizhan', '百战程序员'];
arr.slice(1, 2) // [itbaizhan'];
arr.slice(2, 6) // ['百战程序员'];
arr.slice() // ['尚学堂', 'itbaizhan', '百战程序员']

如果 slice 方法的参数是负数,则表示倒数计算的位置

var arr = ['尚学堂', 'itbaizhan', '百战程序员'];
arr.slice(-2) // ['itbaizhan', '百战程序员']
arr.slice(-2, -1) // ['itbaizhan']

如果第一个参数大于等于数组长度,或者第二个参数小于第一个参数,则返回空数组

var arr = ['尚学堂', 'itbaizhan', '百战程序员'];
arr.slice(4) // []
arr.slice(2, 1) // []

数组方法_splice()

splice 方法用于删除原数组的一部分成员,并可以在删除的位置添加新的数组成员,返回值是被删除的元素。注意,该方法会改变原数组

arr.splice(start, count, addElement1,addElement2, ...);

splice 的第一个参数是删除的起始位置(从0开始),第二个参数是被删除的元素个数。如果后面还有更多的参数,则表示这些就是要被插入数组的新元素

var arr = ['a', 'b', 'c', 'd', 'e', 'f'];
arr.splice(4, 2) // ["e", "f"]
arr // ["a", "b", "c", "d"]
var arr = ['a', 'b', 'c', 'd', 'e', 'f'];
arr.splice(4, 2, 1, 2) // ["e", "f"]
arr // ["a", "b", "c", "d", 1, 2]

起始位置如果是负数,就表示从倒数位置开始删除

var arr = ['a', 'b', 'c', 'd', 'e', 'f'];
arr.splice(-4, 2) // ["c", "d"]

如果只是单纯地插入元素, splice 方法的第二个参数可以设为 0

var arr = [1, 1, 1];
arr.splice(1, 0, 2) // []
arr // [1, 2, 1, 1]

如果只提供第一个参数,等同于将原数组在指定位置拆分成两个数组

var arr = [1, 2, 3, 4];
arr.splice(2) // [3, 4]
arr // [1, 2]

数组方法_sort()

sort 方法对数组成员进行排序,默认是按照字典顺序排序。排序后,原数组将被改变

['d', 'c', 'b', 'a'].sort()
// ['a', 'b', 'c', 'd']
[4, 3, 2, 1].sort()
// [1, 2, 3, 4]
[11, 101].sort()
// [101, 11]
[10111, 1101, 111].sort()
// [10111, 1101, 111]

特别提示
sort 方法不是按照大小排序,而是按照字典顺序。也就是说,数值会被先转成字符串,再按照字典顺序进行比较,所以 101 排在11 的前面

数组方法_indexOf()/lastIndexOf()

indexOf 方法返回给定元素在数组中第一次出现的位置,如果没有出现则返回 -1

var arr = ['a', 'b', 'c'];
arr.indexOf('b') // 1
arr.indexOf('y') // -1

indexOf 方法还可以接受第二个参数,表示搜索的开始位置

['尚学堂', '百战程序员','itbaizhan'].indexOf('尚学堂', 1) // -1

lastIndexOf 方法返回给定元素在数组中最后一次出现的位置,如果没有出现则返回 -1

var arr = [2, 5, 9, 2];
arr.lastIndexOf(2) // 3
arr.lastIndexOf(7) // -1

温馨提示
这两个方法不能用来搜索 NaN 的位置,即它们无法确定数组成员是否包含 NaN
这是因为这两个方法内部,使用严格相等运算符( === )进行比较,而 NaN 是唯一一个不等于自身的值

[NaN].indexOf(NaN) // -1
[NaN].lastIndexOf(NaN) // -1

字符串数组实操

字符串反序

要点提示
1 字符串与数组的转换
2 数组反转排序

var str = "itbaizhan";
console.log(str.split("").reverse().join(""));

将一段字符串变成驼峰命名法

温馨提示
在编程中,有个好的规范是很有必要的,从最基本的变量命名开始,命名写的好,后面找bug维护也容易很多

驼峰命名法
1 大驼峰:每个组成单词的首字母大小(HelloWorld)
2 小驼峰:组成单词的第二个单词的首字母大写(helloWorld)

var str = "hello-world";
var arr = str.split('-');
var newstr = "";
for (var i = 0; i < arr.length; i++) {var word = arr[i];newstr += word.charAt(0).toUpperCase() + word.substr(1);
}
console.log(newstr)

二维数组转化一维数组

要点提示
1 循环外部数组,判断内部元素那个是嵌套的二维数组
2 根据Array.isArray()判断元素类型
3 嵌套的二维数组循环取出元素放入到外部数组中

var arr = [1,2,[3,4],5,[6,7],8,9];
var result = [];
for (var i = 0; i < arr.length; i++) {if (Array.isArray(arr[i])) {for (var j = 0; j < arr[i].length;
j++) {result.push(arr[i][j]);}}else {result.push(arr[i]);}
}
console.log(result);

数组去重

温馨提示
数组去重是典型的JavaScript面试题

// 方案一
var arr = [6,1,1,3,2,4,5,6,1];
var array = [];
for(var i = 0;i<arr.length;i++){if(array.indexOf(arr[i]) === -1){array.push(arr[i])}
}
console.log(array);
// 方案二
var arr = [6,1,1,3,2,4,5,6,1];
for(var i = 0;i<arr.length;i++){for(var j = i+1;j<arr.length;j++){if(arr[i] == arr[j]){arr.splice(j,1);j--}}
}
console.log(arr)

数组排序

温馨提示
数组排序的方案有很多,目前讲解的方案是:冒泡排序

    var arr = [8,2,6,4,5]for (var i = 0; i < arr.length - 1; i++) {console.log("比较轮数:"+(i+1));for (var j = 0; j < arr.length - 1 - i;j++) {if (arr[j] > arr[j + 1]) {var temp = arr[j];arr[j] = arr[j + 1];arr[j + 1] = temp;}console.log("每轮比较次数:" + (j+1));}console.log(arr);}

函数与对象

JavaScript:字符串与数组相关推荐

  1. Javascript字符串及数组赋值区别

    最近做一个分页的javascript程序,需要先将tbody下面的tr标签全部删除,然后再append新的tr,使用下面的代码 var trs=$d("tbdoys").getEl ...

  2. JavaScript字符串、数组、对象方法总结

    字符串方法 示例字符串: const str = "hello,kitty,hello,vue "; 一.基本方法 charAt() 返回指定索引的字符 startsWith() ...

  3. html javascript 字符串和数组互转 字符串拼接 数组拼接

    <!DOCTYPE html> <!DOCTYPE html> <html lang="en"> <head><meta ch ...

  4. javascript 中 split 函数分割字符串成数组

    分割字符串成数组的方法有很多,不过使用最多的还是split函数 <script language="javascript"> str="2,2,3,5,6,6 ...

  5. JavaScript中的数组和字符串

    知识内容: 1.JavaScript中的数组 2.JavaScript中的字符串 一.JavaScript中的数组 1.JavaScript中的数组是什么 数组指的是数据的有序列表,每种语言基本上都有 ...

  6. javascript中的字符串和数组的互转

    javascript中的数组转换成字符串用toString(),或者用join(). 将数组和字符串用+连接,赋给一个变量,这个变量自动转变成字符串了. 字符串转换成数组用split(',') < ...

  7. 【JavaScript 笔记 】— 基础语法(数据类型、字符串、数组、对象、Map、Set、iterable、函数基础)

    JavaScript个人笔记 数据类型和变量 浮点数的相等比较 null 和 undefined == 与 === strict模式 字符串 模板字符串 字符串常用方法 数组 数组常用方法 对象 条件 ...

  8. java中字符串和数组如何比较_[Java教程]javascript中数组和字符串的方法比较

    [Java教程]javascript中数组和字符串的方法比较 0 2016-07-19 23:00:05 ×目录[1]可索引 [2]转换 [3]拼接[4]创建[5]位置 前面的话 字符串和数组有很多的 ...

  9. javascript字符串分割为数组

    javascript字符串分割为数组 ps:本人亲测,阿里云2核4G5M的服务器性价比很高,新用户一块多一天,老用户三块多一天,最高可以买三年,感兴趣的可以戳一下:阿里云折扣服务器 分割数组的时候用s ...

最新文章

  1. 日常工作问题解决:centos/linux系统如何检测端口是否打开
  2. python global用法_14_手把手教你学Python之函数(下)
  3. 中国大学moocpython笔记_用Python玩转数据,中国大学MOOC(慕课)答案公众号搜题
  4. MVC 顶层设计-ModelAndView
  5. 面试官系统精讲Java源码及大厂真题 - 22 ArrayBlockingQueue 源码解析
  6. 大学生学图像处理计算机要求,重点大学计算机教材:数字图像处理
  7. laravel 集成采集_Laravel 使用 QueryList 轻松采集网页
  8. 前端开发~uni-app ·[项目-仿糗事百科] 学习笔记 ·000【前言】
  9. PHP数组学习(一)
  10. Python 机器学习——解决过拟合的方法
  11. Forms(The Definitive Guild to Django)
  12. 南方电网两栖机器人_南方电网发力特高压、人工智能、充电桩等新基建项目
  13. 计算机组装与维护毕业论文范文,计算机应用毕业论文 计算机组装与维护
  14. 国内外优秀程序员的博客全在这了,请查收
  15. Liunx配置tomcat
  16. 经典语录,至理名言,人生百态
  17. LDAP ObjectClass 详解
  18. 英语口语100之每日十句口语
  19. IIIT5K数据提取预处理
  20. c语言的复试笔试题目,c语言面试最必考的十道试题,求职必看!!!

热门文章

  1. 数据库客户端dbeaver
  2. 如何打造一个成功的MES系统,我们又需要注意些什么?
  3. 如何快速记住一张表?
  4. NAACL 2019开源论文:基于胶囊网络的知识图谱完善和个性化搜索
  5. 程序员与产品经理的正确相处之道
  6. 2023最新SSM计算机毕业设计选题大全(附源码+LW)之java民宿预定管理系统20sxh
  7. Ubuntun20.04安装wifi驱动
  8. JAVA后端笔试试题(一)
  9. What?!人工智能还没有人类四岁儿童聪明?
  10. nodejs + vue环境搭建