ES6 | let 关键字 + const关键字 + 箭头函数 + rest参数 + 扩展运算符 ... + Symbol + 迭代器 + 生成器 + 变量的解构赋值 + 模板字符串
目录
ECMASript 相关介绍
ECMASript 6 新特性
let 关键字
const关键字
变量的解构赋值
模板字符串
简化对象写法
箭头函数 =>
参数默认值
rest参数
扩展运算符 ...
Symbol
迭代器
生成器
《阮一峰 ECMAScript 6 (ES6) 标准入门教程 第三版》
https://www.bookstack.cn/read/es6-3rd/docs-intro.md
我愿称他为我的神!!!里面解释的好详细
ECMASript 相关介绍
- ECMAScript 是由 Ecma 国际通过 ECMA-262 标准化的脚本程序设计语言
- TC39(Technical Committee 39)是推进 ECMAScript 发展的委员会。其会员都是公司(其中主要是浏览器厂商,有苹果、谷歌、微软、因特尔等)。TC39 定期召开会议,会议由会员公司的代表与特邀专家出席;
ECMASript 6 新特性
let 关键字
- 1) 不允许重复声明
- 2) 块儿级作用域
- 3) 不存在变量提升
- 4) 不影响作用域链
// let 声明变量的格式let a;let b, c;let d = 100;let e = 200, f = 'HAHA', g = [];// 1. let 不能重复声明变量 var 可以let star = 'pink';let star = '刘德华'; //Uncaught SyntaxError: Identifier 'star' has already been declared// 2.let 声明的变量是块级作用域里的变量 if else while for// 之前的有 全局变量,函数,eval(严格模式){let girl = '蒋依依';}console.log(girl); // 报错 not defined// 3. let 不存在变量提升// 使用var 声明变量时,会把var声明的变量提前,但是不赋值console.log(song); // undefinedvar song = 'HAHA';console.log(sing); // undefinedlet sing = 'HAHA'; // 报错// 4. 不影响作用域链{let school = 'zcst';function fn() {console.log(school); // 向上一级找school变量}fn();}
let 经典案例
<script>// 获取div元素对象let items = document.querySelectorAll('.item');// 遍历并绑定事件// for (var i = 0; i < items.length; i++) {// // 这里用var声明变量,i 会先增加到3 然后再执行下面的// items[i].onclick = function () {// // 修改当前元素的背景颜色// items[i].style.backgroundColor = 'blue'; // 报错// }// }for (let i = 0; i < items.length; i++) {// 计数器i只在for循环体内有效,在循环体外引用就会报错。// 这里用let 声明变量,具有块级作用域,所以items[i]里面的i是根据let i 来变化items[i].onclick = function () {// 修改当前元素的背景颜色// this.style.backgroundColor = 'blue';items[i].style.backgroundColor = 'blue'; // 报错}}</script>
变量
i
是let
声明的,当前的i
只在本轮循环有效,所以每一次循环的i
其实都是一个新的变量
const关键字
- 1) 声明必须赋初始值
- 2) 标识符一般为大写
- 3) 不允许重复声明
- 4) 值不允许修改
- 5) 块儿级作用域
- const 实际上保证的,并不是变量的值不得改动,而是变量指向的那个内存地址所保存的数据不得改动。
- 对于简单类型的数据(数值、字符串、布尔值),值就保存在变量指向的那个内存地址,因此等同于常量。
- 对于复合类型的数据(主要是对象和数组),变量指向的内存地址,保存的只是一个指向实际数据的指针,const只能保证这个指针是固定的(即总是指向另一个固定的地址),至于它指向的数据结构是不是可变的,就完全不能控制了。
// 声明常量const SCHOOL = 'zcst';console.log(SCHOOL); // zcst// 1. 一定要初始值const A; // 错误// 2. 一般常量使用大写(潜规则)// 3. 常量的值不能修改// 4. 块级作用域{const PLAYER = 'HAHA';}console.log(PLAYER); // 报错// 5. 对于数组和对象的元素修改,不算做对常量的修改,不会报错const TEAM = [1, 3, 5, 7];TEAM.push(7);console.log(TEAM); // [1,3,5,7,7]
变量的解构赋值
- ES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称 为解构赋值。
// 1. 数组的结构const F4 = ['小沈阳', '刘能', '赵四'];let [xiao, liu, zhao] = F4;console.log(xiao); //小沈阳console.log(liu); // 刘能console.log(zhao); // 赵四
可以从数组中提取值,按照对应位置,对变量赋值。
// 2. 对象的解构const shan = {name: '赵本山',xiaopin: function () {console.log('我可以演小品');}};shan.xiaopin(); // 我可以演小品// 相当于let { xiaopin } = shan;xiaopin();
对象的属性没有次序,变量必须与属性同名,才能取到正确的值。
如果解构失败,变量的值等于
undefined
。
模板字符串
- 1) 字符串中可以出现换行符
- 2) 可以使用 ${xxx} 形式输出变量
如果使用模板字符串表示多行字符串,所有的空格和缩进都会被保留在输出之中。
// ES6 引入新的声明字符串的方式// 1. 声明let str = `我也是一个字符串`;console.log(str, typeof str); //我也是一个字符串 string// 2. 内容中可以直接出现换行符let str1 = `<ul><li>沈腾</li><li>玛丽</li><li>艾伦</li></ul > `;// 3. 变量拼接let loveset = 'pink';let out = `${loveset}xxx是我心中最帅的颜色`;console.log(out); // pinkxxx是我心中最帅的颜色
简化对象写法
ES6 允许在大括号里面,直接写入变量和函数,作为对象的属性和方法。这样的书写更加简洁
// ES6 允许在大括号里面,直接写入变量和函数,作为对象的属性和方法let name = 'ldh';let change = function () {console.log('我们可以改变你');}const school = {name,change,improve() {console.log('我可以提高你的技能');}}// 相当于// const school = {// name:name,// change:change// improve: function() {// console.log('我可以提高你的技能');// }// }console.log(school);
箭头函数 =>
// ES6 中允许使用 箭头 => 定义函数// 声明一个函数let fn = function () { }let fn1 = (a, b) => {return a + b;}// 调用函数let result = fn1(1, 2);console.log(result); // 3
- 1.箭头函数中 this 是静态的,this 始终指向函数声明时所在作用域下的this值
function getName() {console.log(this.name);}let getName2 = () => {console.log(this.name);}// 设置window对象的name 属性window.name = 'ldh';const star = {name: '德华'}// 调用getName(); // ldhgetName2(); // ldh// call 方法调用// call() 方法调用一个函数。简单理解为调用函数的方式,但是它可以改变函数的 this 指向。getName.call(star); // 德华getName2.call(star); // ldh
- 2. 不能作为构造函数实例化对象
let Person = (name, age) => {this.name = name;this.age = age;}let me = new Person('ldh', 18);console.log(me); // TypeError: Person is not a constructor
- 3. 不能使用arguments 变量
let fn2 = () => {console.log(arguments);}fn2(1, 2, 3); // ReferenceError: arguments is not defined
- 4. 箭头函数的简写
(1) 省略小括号 :当形参有且只有一个的时候
(2) 省略花括号{}:当代码只有一条语句的时候
// 4. 箭头函数的简写// (1) 省略小括号 :当形参有且只有一个的时候let add = n => {return n + n;}console.log(add(9)); // 18// (2) 省略花括号{}:当代码只有一条语句的时候// 此时return必须省略,而且语句的执行结果就是函数的返回值let pow = n => n * n;console.log(pow(5)); // 25
箭头函数实践
- 箭头函数适合与this 无关的回调,定时器,数组的方法回调
- 箭头函数不适合与this 有关的回调,事件回调,对象的方法
<body><div id="ad"></div><script>// 需求-1:点击div 2s 后颜色变成粉色let ad = document.querySelector('#ad');ad.addEventListener('click', function () {let _this = this; // this 指向ad// 原来的函数声明setTimeout(function () {console.log(this); // 定时器指向windowconsole.log(_this); // 指向ad}, 2000)// 使用箭头函数 this指向函数声明时所在作用域下的this值setTimeout(() => {this.style.backgroundColor = 'pink';}, 2000)})// 需求-2:从数组中返回偶数的元素const arr = [1, 2, 4, 56, 75, 324];// 原来做法const result = arr.filter(function (item) {if (item % 2 === 0) {return true;} else {return false;}})console.log(result);// 箭头函数做法const result1 = arr.filter(item => item % 2 === 0) // 返回item%2 === 0的数console.log(result1);// 箭头函数适合与this 无关的回调,定时器,数组的方法回调// 箭头函数不适合与this 有关的回调,事件回调,对象的方法</script>
</body>
参数默认值
- ES6 允许给函数参数赋值 初始值
- 1. 形参初始值 具有默认值的参数,一般位置要靠后(潜规则)
function add(a, b, c = 10) {return a + b + c;}let result = add(1, 2);console.log(result); // 13
- 2. 与解构赋值结合
传参的时候有初始值,也有实参,按照实参来进行
传参的时候有初始值,没有实参,按照初始值来进行
function connect({ host = '127.0.0.1', username, password, port }) {console.log(host);console.log(username);console.log(password);console.log(port);}connect({host: 'localhost',username: 'root',password: 'root',port: 3306})
rest参数
- ES6 引入 rest 参数(形式为
...变量名
),用于获取函数的多余参数,这样就不需要使用arguments
对象了。 - rest 参数搭配的变量是一个数组,该变量将多余的参数放入数组中。
- function date(...args){};
- 注意,rest 参数之后不能再有其他参数(即只能是最后一个参数),否则会报错
// ES6 引入rest 参数,用于获取函数的实参,代替arguments// ES5 获取实参的方式function date() {console.log(arguments); // 对象的形式}date('哈利', '小天狼星', '詹姆');// rest 参数function date1(...args) {console.log(args); // 数组的形式}date1('破特', '布莱克', '韦斯莱'); // ["破特", "布莱克", "韦斯莱"]// rest 参数必须放到参数最后function fn(a, b, ...args) {console.log(a); // 1console.log(b); // 2console.log(args); // [3,3,4,5]}fn(1, 2, 3, 3, 4, 5);
扩展运算符 ...
- 扩展运算符(spread)是三个点(
...
)。它好比 rest 参数的逆运算,将一个数组转为用逗号分隔的参数序列
// ... 扩展运算符 能将 数组转换为逗号分隔的参数序列// 声明一个数组const tfboys = ['易烊千玺', '王俊凯', '王源']; // =>'易烊千玺', '王俊凯', '王源'// 声明一个函数function chunwan() {console.log(arguments);}chunwan(tfboys); // ["易烊千玺", "王俊凯", "王源"]chunwan(...tfboys); // chunwan("易烊千玺", "王俊凯", "王源")
- 可以合并数组
// 1. 数组的合并const kuaizi = ['王太利', '肖央'];const fenghuang = ['曾毅', '玲花'];// concat()连接多个数组// const zuixuanxiaopingguo = kuaizi.concat(fenghuang);// console.log(zuixuanxiaopingguo);const zuixuanxiaopingguo = [...kuaizi, ...fenghuang];console.log(zuixuanxiaopingguo); // ["王太利", "肖央", "曾毅", "玲花"]
数组的克隆 浅拷贝
// 2. 数组的克隆 浅拷贝const sanzhihua = ['E', 'G', 'M'];const sanyecao = [...sanzhihua];console.log(sanyecao); // ["E", "G", "M"]
将伪数组转为真正的数组
// 3. 将伪数组转为真正的数组const divs = document.querySelectorAll('div');console.log(typeof divs); // Object// typeof 判断数组类型的数据时,一律返回的是objectconst divArr = [...divs];console.log(divArr); // [div, div, div]
Symbol
- ES6 引入了一种新的原始数据类型
Symbol
,表示独一无二的值。 - 它是 JavaScript 语言的第七种数据类型,USONB 前六种是:
undefined
、null
、布尔值(Boolean)、字符串(String)、数值(Number)、对象(Object)。 - Symbol 值不能与其他类型的值进行运算,会报错。
// 创建 symbollet s = Symbol();console.log(s, typeof s); // Symbol() "symbol"let s2 = Symbol('哈哈');console.log(s2); // Symbol(哈哈)let s3 = Symbol('哈哈');console.log(s2 === s3); // false
注意,
Symbol
函数的参数只是表示对当前 Symbol 值的描述,因此相同参数的Symbol
函数的返回值是不相等的。
// Symbol.for 创建let s4 = Symbol.for('啥');let s5 = Symbol.for('啥');console.log(s4 === s5); // true
我们希望重新使用同一个 Symbol 值,
Symbol.for()
方法可以做到这一点。它接受一个字符串作为参数,然后搜索有没有以该参数作为名称的 Symbol 值。如果有,就返回这个 Symbol 值,否则就新建一个以该字符串为名称的 Symbol 值,并将其注册到全局。
Symbol创建对象属性
- 在对象的内部,使用 Symbol 值定义属性时,Symbol 值必须放在方括号之中。
<script>// 向对象中添加方法 up downlet game = {name: '俄罗斯方块',up: function () { },down: function () { }}// 声明一个对象let methods = {up: Symbol(),down: Symbol()}// 向对象中添加方法game[methods.up] = function () {console.log('我可以改变这个形状');}game[methods.down] = function () {console.log('我可以快速下降');}console.log(game);let youxi = {name: '狼人杀',// 添加方法[Symbol('say')]: function () {console.log('我可以发言');},[Symbol('zibao')]: function () {console.log('我可以自爆');}}console.log(youxi);</script>
Symbol 内置值
- 除了定义自己使用的 Symbol 值以外,ES6 还提供了 11 个内置的 Symbol 值,指向语言内部使用的方法。可以称这些方法为魔术方法,因为它们会在特定的场景下自动执行。
Symbol.hasInstance
|
当其他对象使用 instanceof 运算符,判断是否为该对
象的实例时,会调用这个方法
|
Symbol.isConcatSpreadable
|
对象的 Symbol.isConcatSpreadable 属性等于的是一个布尔值,表示该对象用于 Array.prototype.concat()时, 是否可以展开。
|
Symbol.species
|
创建衍生对象时,会使用该属性
|
Symbol.match
|
当执行 str.match(myObject) 时,如果该属性存在,会调用它,返回该方法的返回值。
|
Symbol.replace
|
当该对象被 str.replace(myObject)方法调用时,会返回该方法的返回值。
|
Symbol.search
|
当该对象被 str.search (myObject)方法调用时,会返回该方法的返回值。
|
Symbol.split
|
当该对象被 str.split(myObject)方法调用时,会返回该方法的返回值。
|
Symbol.iterator
|
对象进行 for...of 循环时,会调用 Symbol.iterator 方法,返回该对象的默认遍历器
|
Symbol.toPrimitive
|
该对象被转为原始类型的值时,会调用这个方法,返回该对象对应的原始类型值。
|
Symbol. toStringTag
|
在该对象上面调用 toString 方法时,返回该方法的返回值
|
Symbol. unscopables
|
该对象指定了使用 with 关键字时,哪些属性会被 with环境排除。
|
Symbol.hasInstance
// 当其他对象使用 instanceof 运算符,判断是否为该对象的实例时,会调用这个方法class Person {static [Symbol.hasInstance](param) {console.log(param);console.log('我被用来检测类型了');}}let o = {};console.log(o instanceof Person);// 判断是否是偶数class Even {static [Symbol.hasInstance](obj) {return Number(obj) % 2 === 0;}}// 等同于// const Even = {// [Symbol.hasInstance](obj) {// return Number(obj) % 2 === 0;// }// };console.log(1 instanceof Even); // falseconsole.log(2 instanceof Even); // true
Symbol.isConcatSpreadable
const arr = [1, 2, 3];const arr2 = [4, 5, 6];arr2[Symbol.isConcatSpreadable] = false;console.log(arr.concat(arr2));
为false的话,用concat连接数组的时候,会把后面的当成一个整体,不会展开
默认是true,把他们展开来连接
迭代器
- 遍历器(Iterator)就是一种机制。它是一种接口,为各种不同的数据结构提供统一的访问机制。任何数据结构只要部署 Iterator 接口,就可以完成遍历操作。
Iterator 的作用有三个:
一是为各种数据结构,提供一个统一的、简便的访问接口;
二是使得数据结构的成员能够按某种次序排列;
三是 ES6 创造了一种新的遍历命令
for...of
循环,Iterator 接口主要供for...of
消费。
Iterator 的遍历过程是这样的
(1)创建一个指针对象,指向当前数据结构的起始位置。也就是说,遍历器对象本质上,就是一个指针对象。 xiyou[Symbol.iterator]()
(2)第一次调用指针对象的next
方法,可以将指针指向数据结构的第一个成员。
(3)第二次调用指针对象的next
方法,指针就指向数据结构的第二个成员。
(4)不断调用指针对象的next
方法,直到它指向数据结构的结束位置。
每一次调用next
方法,都会返回数据结构的当前成员的信息。具体来说,就是返回一个包含value
和done
两个属性的对象。其中,value
属性是当前成员的值,done
属性是一个布尔值,表示遍历是否结束。
注: 需要自定义遍历数据的时候,要想到迭代器。
// 声明一个数组const xiyou = ['唐僧', '孙悟空', '猪八戒', '沙僧'];// 使用 for...of 遍历数组for (let v of xiyou) {console.log(v); // v 就是 每一个xiyou里面的每一个值}console.log(xiyou); // 唐僧 孙悟空 猪八戒 沙僧// 迭代器原理let iterator = xiyou[Symbol.iterator]();// 调用对象的next方法console.log(iterator.next()); // 唐僧console.log(iterator.next()); // 孙悟空console.log(iterator.next()); // 猪八戒console.log(iterator.next()); // 沙僧console.log(iterator.next()); // undefined
遍历一个对象,返回的是对象里面的数组的成员
<script>// 声明一个对象const banji = {name: 'jk7ban',stus: ['mzp', 'lzw', 'wkh', 'grb', 'lxw', 'wwf', 'zzh'],[Symbol.iterator]() {let index = 0;// let _this = this;return {next: function () {if (index < _this.stus.length) {const result = { value: _this.stus[index], done: false };// 让下标自增index++;return result;} else {return { value: undefined, done: true };}}};}}// 遍历这个对象,返回的是对象里面的数组的成员for (let v of banji) {console.log(v);}</script>
生成器
- 生成器函数是 ES6 提供的一种异步编程解决方案,语法行为与传统函数完全不同
代码说明:1) * 的位置没有限制2) 生成器函数返回的结果是迭代器对象,调用迭代器对象的 next 方法可以得到yield 语句后的值3) yield 相当于函数的暂停标记,也可以认为是函数的分隔符,每调用一次 next方法,执行一段代码4) next 方法可以传递实参,作为 yield 语句的返回值
<script>// 生成器其实是一个特殊的函数// 异步编程 之前用的是 纯回调函数// yield 函数代码的分隔符function* gen() {console.log('HAHA generator');yield '一直没有耳朵';console.log('HAHA2');yield '一只没有尾巴';console.log('HAHA3');yield ' 真奇怪';console.log('HAHA4');}let iterator = gen();// console.log(iterator); // 返回的是迭代器对象 里面有next方法 gen {<suspended>}console.log(iterator.next()); // HAHA generator 执行的是第一个分隔符yield之前的console.log(iterator.next()); // HAHA2 执行的是第二个分隔符yield之前的console.log(iterator.next()); // HAHA3console.log(iterator.next()); // HAHA4// 遍历的是 gen() 里面的所有可输出的// for (let v of gen()) {// console.log(v);// }</script>
生成器函数参数
<script>function* gen(arg) {console.log(arg);let one = yield 111;console.log(one);let two = yield 222;console.log(two);let three = yield 333;console.log(three);}// 执行获取迭代器对象let iterator = gen('AAA');console.log(iterator.next()); // AAA {value: 111, done: false}// next 参数可以传入实参// 给第二个next传参,他会作为第一个yield语句整体的返回结果,以此类推console.log(iterator.next('BBB')); // {value: 222, done: false}console.log(iterator.next('CCC')); // {value: 222, done: false}console.log(iterator.next('DDD')); // {value: undefined, done: true}</script>
生成器函数实例1
1s 后控制台输出111 然后2s后 输出222 然后3s 后输出333
如果按照原来的写法,回调地狱,一直回调,看起来混乱
// 回调地狱 层层回调 一层套一层// setTimeout(function () { }, 1000)setTimeout(() => {console.log(111);setTimeout(() => {console.log(222);setTimeout(() => {console.log(333);}, 3000);}, 2000);}, 1000);
按照生成器函数
// 用生成器函数function one() {setTimeout(() => {console.log(111);iterator.next();}, 1000);}function two() {setTimeout(() => {console.log(222);iterator.next();}, 2000);} function three() {setTimeout(() => {console.log(333);// iterator.next();}, 3000);}function* gen() {// 在生成器函数里面调用这三个函数?yield one();yield two();yield three();}// 调用生成器函数let iterator = gen();iterator.next();
生成器函数实例2
<script>// 模拟获取 用户数据 订单数据 商品数据function getUsers() {setTimeout(() => {let data = '用户数据';// 调用next方法,并且将数据传入iterator.next(data); // 这是第二次调入next(),这里的实参将会作为第一个yield返回的结果}, 1000);}function getOrder() {setTimeout(() => {let data = '订单数据';// 调用next方法,并且将数据传入iterator.next(data); // 这是第三次调入next(),这里的实参将会作为第二个yield返回的结果}, 1000);}function getGoods() {setTimeout(() => {let data = '商品数据';// 调用next方法,并且将数据传入iterator.next(data); // 这是第四次调入next(),这里的实参将会作为第三个yield返回的结果}, 1000);}function* gen() {let users = yield getUsers();console.log(users);let order = yield getOrder();console.log(order);let goods = yield getGoods();console.log(goods);}// 调用生成器函数let iterator = gen();iterator.next();</script>
ES6 | let 关键字 + const关键字 + 箭头函数 + rest参数 + 扩展运算符 ... + Symbol + 迭代器 + 生成器 + 变量的解构赋值 + 模板字符串相关推荐
- es6 箭头函数 rest参数 扩展运算符
Es6 箭头函数 语法: 普通函数: fn=function(){} 箭头函数: fn=()=>{} 特性: this是静态的,this始终指向函数声明时所在作用域下的this的值(使用call ...
- 2021-02-24let和const,变量的解构赋值,函数扩展
文章目录 let 1.ES6简介 2.let关键字 2.1 不存在变量提升 2.2 暂时性死区 2.3 不允许重复声明 3.块级作用域 3.1 为什么需要块级作用域 缺点1:内部变量可能会覆盖外层的变 ...
- (34)2021-02-24(ES6变量的解构赋值)
ES6变量的解构赋值 一. 变量的解构赋值 1.什么是解构 2.数组解构赋值 不完全解构 3.对象解构赋值 方法解构 注意点 4.字符串解构 5.函数参数的解构赋值 6.用途 6.1 交换变量的值 6 ...
- vue解构赋值_前端开发es6知识 模块化、解构赋值、字符串模板
项目开发中一些常用的es6知识,主要是为以后分享小程序开发.node+koa项目开发以及vueSSR(vue服务端渲染)做个前置铺垫. 项目开发常用es6介绍1.块级作用域 let const 2.箭 ...
- let的解构赋值_前端开发es6知识 模块化、解构赋值、字符串模板
项目开发中一些常用的es6知识,主要是为以后分享小程序开发.node+koa项目开发以及vueSSR(vue服务端渲染)做个前置铺垫. 项目开发常用es6介绍 1.块级作用域 let const 2. ...
- 【ES6】变量的解构赋值
[ES6]变量的解构赋值 一.什么叫解构赋值? 二.解构赋值有哪些分类?写法? 1)对数组的解构赋值 2)对对象的解构赋值 3)对字符串的解构赋值 4)对数值和布尔值的解构赋值 5)对函数参数的解构赋 ...
- ES6的新特性(3)——变量的解构赋值
变量的解构赋值 数组的解构赋值 基本用法 ES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构(Destructuring). let a = 1; let b = 2; le ...
- Vue2.x—理解vuex核心概念action(使用到ES6的变量的解构赋值)
Action Action 类似于 mutation,不同在于: Action 提交的是 mutation,而不是直接变更状态. Action 可以包含任意异步操作. 让我们来注册一个简单的 acti ...
- ES6学习笔记二 新的声明方式和变量的解构赋值!
新的声明方式 在ES5的时候,我们只有一个声明方式,var!但是在es6中,声明进行了扩展,我们加上ES5的var的申明方式,我们有了三种声明方式: var:它是variable的简写,可以理解成变量 ...
最新文章
- CSS表格中的一些属性
- activiti 工作流 springboot 后台框架平台 集成代码生成器 shiro 权限
- Mysql分析-profile详解
- 2016/07 — 周年记录
- C++11特性(模板类 initializer_list)
- JavaScript -- 时光流逝(三):js中的 String 对象的方法
- 1452.接水问题(思维)
- python 关于excelcsv与cookie的部分笔记
- 使用tinylog 1.1改进您在Java EE应用程序中的登录
- AS3之BitmapData学习整理
- 张正友标定算法理论及算法实现
- Java基础小常识-final,抽象类,接口-(11)
- 程序设计中为什么要解耦?
- Java中守护线程和本地线程区别,这特么太重要了!
- 首届“梧桐杯”大数据应用创新大赛复赛晋级名单发布
- 西瓜错时上市销售,提高经济效益的背后是技术支持!
- Qt,C++开发炫酷圆形扇形菜单面板
- Git 常用提交操作步骤
- 整理英语句子:将首字母大写,单词之间只能一个空格,最后加句号
- Latex中参考文献的写作方法
热门文章
- ubuntu20 开机启动_Ubuntu20.04 双网卡 共享上网解决方案
- 【oracle】配置恢复管理器Configuring Recovery Manager
- ag-grid-vue纵向合并单元格
- 001-使用docker desktop for mac
- 数据结构——拉链法(链地址法)
- MapReduce工作流程图
- vimeo下载_通过Vimeo的API喜欢,关注列表和上传
- Login with Vimeo in iOS App using oAuth tutorial
- 《黄帝内经.上古天真论》养生秘诀节选-1
- 吴京砸向MOSS的伏特加,被做成了串口助手