一、数据类型

  • 基本类型:String、Number、Boolean、Undefined、Null、Symbol、bigInt
  • 引用类型:Object、Function
  • 基本类型的数据是存放在栈内存中的,而引用类型的数据是存放在堆内存中的

1.基本类型

var num1 = 5;
var num2 = num1;

基本类型的复制就是在栈内存中开辟出了一个新的存储区域用来存储新的变量,这个变量有它自己的值,只不过和前面的值一样,所以如果其中一个的值改变,则不会影响到另一个。

新增类型:bigInt 可用来表示大于 253 - 1 的整数,这原本是 Javascript中可以用_number_来表示的最大数字。

可以用在一个整数字面量后面加 n 的方式定义一个 BigInt ,如:10n,或者调用函数BigInt()。

const theBiggestInt = 9007199254740991n;
const alsoHuge = BigInt(9007199254740991); // 9007199254740991n

2.引用类型

var obj1 = new Object();
var obj2 = obj1;

定义一个对象其实是在栈内存中存储了一个指针,这个指针指向堆内存中该对象的存储地址。复制给另一个对象的过程其实是把该对象的地址复制给了另一个对象变量,两个指针都指向同一个对象,所以若其中一个修改了,则另一个也会改变。

3.数据类型判断

  • typeof

    typeof 是一个操作符,其右侧跟一个一元表达式,并返回这个表达式的数据类型。返回的结果用该类型的字符串(全小写字母)形式表示,包括以下 7 种:number、boolean、symbol、string、object、undefined、function

typeof 2; // number
typeof undefined; // undefined
typeof '222'; // string
typeof true; // boolean
typeof Symbol(); // symbol
typeof 1n; // bigint
typeof BigInt('1'); // bigint
typeof null; // object
typeof {}; // object
typeof []; // object
typeof new Function(); // function
typeof new Date(); // object
typeof new RegExp(); // object

对于基本类型,除 null 以外,均可以返回正确的结果。

对于引用类型,除 function 以外,一律返回 object 类型。

对于 null ,返回 object 类型。

对于 function 返回 function 类型。

其中,null 有属于自己的数据类型 Null ,引用类型中的 数组、日期、正则 也都有属于自己的具体类型,而 typeof 对于这些类型的处理,只返回了处于其原型链最顶端的 Object 类型。

  • instanceof

    instanceof 是用来判断 A 是否为 B 的实例,表达式为:A instanceof B,如果 A 是 B 的实例,则返回 true,否则返回 false。
    在这里需要特别注意的是:instanceof 检测的是原型,我们用一段伪代码来模拟其内部执行过程:

instanceof (A, B) = {var L = A.__proto__;var R = B.prototype;if(L === R) {// A的内部属性 __proto__ 指向 B 的原型对象return true;}return false;
}

当 A 的 __proto__ 指向 B 的 prototype 时,就认为 A 就是 B 的实例

[] instanceof Array; // true
{} instanceof Object; // true
new Date() instanceof Date;// true
function Person(){};
new Person() instanceof Person; // true[] instanceof Object; // true
newDate() instanceof Object; // true
newPerson instanceof Object; // true

我们发现,虽然 instanceof 能够判断出 [ ] 是Array的实例,但它认为 [ ] 也是Object的实例
[ ].__proto__ 指向 Array.prototype,而 Array.prototype.__proto__ 又指向了Object.prototype,最终 Object.prototype.__proto__ 指向了null,标志着原型链的结束。因此,[]、Array、Object 就在内部形成了一条原型链:

从原型链可以看出,[] 的 __proto__ 直接指向Array.prototype,间接指向 Object.prototype,所以按照 instanceof 的判断规则,[] 就是Object的实例。依次类推,类似的 new Date()、new Person() 也会形成一条对应的原型链 。
因此,instanceof 只能用来判断两个对象是否属于实例关系, 而不能判断一个对象实例具体属于哪种类型

  • constructor

    当一个函数 F被定义时,JS引擎会为F添加 prototype 原型,然后再在 prototype上添加一个 constructor 属性,并让其指向 F 的引用。

当执行 var f = new F() 时,F 被当成了构造函数,f 是F的实例对象,此时 F 原型上的 constructor 传递到了 f 上,因此 f.constructor == F

F 利用原型对象上的 constructor 引用了自身,当 F 作为构造函数来创建对象时,原型上的 constructor 就被遗传到了新创建的对象上, 从原型链角度讲,构造函数 F 就是新对象的类型。

细节问题:

null 和 undefined 是无效的对象,因此是不会有 constructor 存在的,这两种类型的数据需要通过其他方式来判断。

函数的 constructor 是不稳定的,这个主要体现在自定义对象上,当开发者重写 prototype 后,原有的 constructor 引用会丢失,constructor 会默认为 Object

  • toString

    toString() 是 Object 的原型方法,调用该方法,默认返回当前对象的 [[Class]] 。这是一个内部属性,其格式为 [object Xxx],其中 Xxx 就是对象的类型。
    对于 Object 对象,直接调用 toString() 就能返回 [object Object] 。而对于其他对象,则需要通过 call / apply 来调用才能返回正确的类型信息。

Object.prototype.toString.call(''); // [object String]
Object.prototype.toString.call(1); // [object Number]
Object.prototype.toString.call(true); // [object Boolean]
Object.prototype.toString.call(Symbol()); // [object Symbol]
Object.prototype.toString.call(undefined); // [object Undefined]
Object.prototype.toString.call(null); // [object Null]
Object.prototype.toString.call(newFunction()); // [object Function]
Object.prototype.toString.call(newDate())=; // [object Date]
Object.prototype.toString.call([]); // [object Array]
Object.prototype.toString.call(newRegExp()); // [object RegExp]
Object.prototype.toString.call(newError()); // [object Error]

二、常用数组遍历方法

1.forEach()遍历数组

let a = [1, 2, 3, 4, 5];
let result = a.forEach((currentValue, currentIndex)=>{console.log(currentValue, currentIndex);// 1 0// 2 1// 3 2// 4 3// 5 4
});
console.log(result);   // undefined 没有返回值
console.log(a);        // [1, 2, 3, 4, 5]
  • 注:forEach中不能使用break和continue关键字
  • 注:forEach中可以使用return来实现continue的效果,无法实现break效果。一经调用,就一定会遍历完。

2.every(fn)判断数组中是否所有元素都满足fn函数中的条件

let a = [1, 2, 3, 4, 5];
let result = a.every((currentValue)=>{return currentValue > 0;
});
console.log(result);   // true  所有元素都大于0result = a.every((currentValue)=>{return currentValue > 1;
});
console.log(result);   // false  1并不大于1
console.log(a);        // [1, 2, 3, 4, 5]

3.filter(fn)返回数组中满足fn函数中条件的集合

let a = [1, 2, 3, 4, 5];
let result = a.filter((currentValue)=>{return currentValue > 4;
});
console.log(result); // [5] 只有5满足条件
console.log(a); // [1, 2, 3, 4, 5]

4.find(fn)返回数组中第一个匹配fn函数中条件的值,没有则返回undefined

let a = [1, 2, 3, 4, 5];
let result = a.find((currentValue)=>{return currentValue > 3;
});
console.log(result); // 4result = a.find((currentValue)=>{return currentValue > 5;
})
console.log(result); // undefined
console.log(a); // [1, 2, 3, 4, 5]

5.findIndex(fn)返回数组中第一个匹配fn函数中条件的索引,没有则返回-1

let a = [1, 2, 3, 4, 5];
let result = a.findIndex((currentValue)=>{return currentValue > 3;
});console.log(result);   // 3
result = a.findIndex((currentValue)=>{return currentValue > 5;
});
console.log(result); // -1
console.log(a); // [1, 2, 3, 4, 5]

6.includes()返回一个布尔值,表示某个数组是否包含给定的值

let a = [1, 2, 3, 4, 5];
let result = a.includes(2);
console.log(result);   // trueresult = a.includes(6);
console.log(result);   // false
console.log(a);        // [1, 2, 3, 4, 5]

7.map(fn)以fn函数中返回值组成新的数组返回

let a = [1, 2, 3, 4, 5];
let result = a.map((v, i)=>{return 9;
});
console.log(result);   // [9, 9, 9, 9, 9]
console.log(a);        // [1, 2, 3, 4, 5]

8.reduce()累计器

let a = [1, 2, 3, 4, 5];
let result = a.reduce((accumulator, currentValue, currentIndex, array)=>{console.log(accumulator, currentValue, currentIndex, array);return accumulator + currentValue;// 5  1 0 [1, 2, 3, 4, 5]  第一次accumulator的值为reduce第二个参数5, currentValue为数组第一个元素// 6  2 1 [1, 2, 3, 4, 5]  第二次accumulator的值为5加上数组a中的第一个值,即是第一次循环时return的值// 8  3 2 [1, 2, 3, 4, 5]  同上// 11 4 3 [1, 2, 3, 4, 5]  同上// 15 5 4 [1, 2, 3, 4, 5]  同上
}, 5);
console.log(result);   // 20 为最终累计的和// 无初始值时,accumulator的初始值为数组的第一个元素,currentValue为数组第二个元素
result = a.reduce((accumulator, currentValue, currentIndex, array)=>{console.log(accumulator, currentValue, currentIndex, array);return accumulator + currentValue;// 1  2 1 [1, 2, 3, 4, 5]// 3  3 2 [1, 2, 3, 4, 5]// 6  4 3 [1, 2, 3, 4, 5]// 10 5 4 [1, 2, 3, 4, 5]
})
console.log(result);   // 15 为最终累计的和
console.log(a);        // [1, 2, 3, 4, 5]

9.some(fn)检查数组中是否含有满足fn函数条件的值

let a = [1, 2, 3, 4, 5];
let result = a.some((currentValue)=>{return currentValue > 2;
});
console.log(result);   // trueresult = a.some((currentValue)=>{return currentValue > 6;
});
console.log(result);   // false
console.log(a);        // [1, 2, 3, 4, 5]
  • 注:以上方法均不改变原数组
  • 注:find(), findIndex(), includes()均为es6语法,ie不支持

三、常用对象遍历方法

1.for-in

for-in会遍历出原型链上的属性,可以通过hasOwnProperty方法来实现过滤

Object.prototype.sexy = '男';
let obj = {id: 1,name: "zhangsan",age: 18
};
for(let key  in obj){console.log(key + '---' + obj[key]);
}
// 输出结果:
// id---1
// name---zhangsan
// age---18
// sexy---男for(let key  in obj){if (obj.hasOwnProperty(key)) {console.log(key + '---' + obj[key]);}
}
// 输出结果:
// id---1
// name---zhangsan
// age---18

2.Object.keys(obj)、Object.values(obj)

该方法返回对象自身属性名、属性值组成的数组,它会自动过滤掉原型链上的属性,然后可以通过数组的 forEach() 方法来遍历

let obj = {id: 1,name: "zhangsan",age: 18
};
console.log(Object.keys(obj));
// 输出结果: obj对象的key组成的数组['id','name','age']console.log(Object.values(obj));// 输出结果: obj对象的value组成的数组['1','zhangsan','18']Object.keys(obj).forEach((key)=>{console.log(key+ '---'+obj[key]);
});
// 输出结果:
// id---1
// name---zhangsan
// age---18

3.Object.getOwnPropertyNames(obj)

该方法返回对象自身属性名组成的数组,包括不可枚举的属性

let obj = {id: 1,name: "zhangsan",age: 18
};
Object.getOwnPropertyNames(obj).forEach((key)=>{console.log(key+ '---'+obj[key]);
});
// 输出结果:
// id---1
// name---zhangsan
// age---18

四、常用字符串操作方法

  • charAt()

    返回给定位置的那个字符

var stringValue = 'hello world';
console.log(stringValue.charAt(1)); // 'e'
  • concat()

    将一或多个字符串拼接起来,返回拼接得到的新的字符串

var stringValue = 'hello ';
var resrult = stringValue.concat('world');
console.log(resrult); // 'hello world'
console.log(stringValue); // 'hello ' 不改变源字符串
  • replace()、replaceAll()

    替换指定字符串

var stringValue = 'cat,bat,sat,fat';
var result = stringValue.replace('at', 'ond');
console.log(result); // 'cond,bat,sat,fat'
var result = stringValue.replaceAll('at', 'ond');
console.log(result); // 'cond,bond,sond,fond'
result = stringValue.replace(/at/g,'ond');
console.log(result); // 'cond,bond,sond,fond'
console.log(stringValue); // 'cat,bat,sat,fat' 不改变源字符串
  • slice()、substring()、substr()

提取字符串的片断,并在新的字符串中返回被提取的部分

substring()方法返回一个索引和另一个索引之间的字符串。语法如下:

str.substring(indexStart, [indexEnd])

注意要点:

substring()提取的字符包含 indexStart 但不包括 indexEnd。

如果indexStart 等于indexEnd,返回一个空字符串。

如果indexEnd省略,则将字符提取到字符串的末尾。

如果任一参数小于0或是NaN,它被视为为0。

如果任何一个参数都大于str.length,则被视为是str.length。

如果indexStart大于indexEnd,则返回交换两者的值之后的结果

var str = 'abcdefghij';
console.log('(1, 2): '   + str.substring(1, 2));   // '(1, 2): b'
console.log('(1, 1): '   + str.substring(1, 1));   // '(1, 1): '
console.log('(-3, 2): '  + str.substring(-3, 2));  // '(-3, 2): ab'
console.log('(-3): '     + str.substring(-3));     // '(-3): abcdefghij'
console.log('(1): '      + str.substring(1));      // '(1): bcdefghij'
console.log('(-20, 2): ' + str.substring(-20, 2)); // '(-20, 2): ab'
console.log('(2, 20): '  + str.substring(2, 20));  // '(2, 20): cdefghij'
console.log('(20, 2): '  + str.substring(20, 2));  // '(20, 2): cdefghij'
console.log(str ); // 'abcdefghij' 不改变源字符串

substr()方法返回从指定位置开始的字符串中指定字符数的字符。语法如下:

str.substr(start, [length])

注意要点:

substr()会从start获取长度为length字符(如果截取到字符串的末尾,则会停止截取)。

如果start是正的并且大于或等于字符串的长度,则返回一个空字符串。

若start为负数,则将该值加上字符串长度后再进行计算(如果加上字符串的长度后还是负数,则从0开始截取)。

如果length为0或为负数,返回一个空字符串。如果length省略,则将字符提取到字符串的末尾。

var str = 'abcdefghij';
console.log('(1, 2): '   + str.substr(1, 2));   // '(1, 2): bc'
console.log('(-3, 2): '  + str.substr(-3, 2));  // '(-3, 2): hi'
console.log('(-3): '     + str.substr(-3));     // '(-3): hij'
console.log('(1): '      + str.substr(1));      // '(1): bcdefghij'
console.log('(-20, 2): ' + str.substr(-20, 2)); // '(-20, 2): ab'
console.log('(20, 2): '  + str.substr(20, 2));  // '(20, 2): '
console.log(str ); // 'abcdefghij' 不改变源字符串

slice()方法返回一个索引和另一个索引之间的字符串,语法如下:

str.slice(beginIndex[, endIndex])

注意要点:

若beginIndex为负数,则将该值加上字符串长度后再进行计算(如果加上字符串的长度后还是负数,则从0开始截取)。

如果beginIndex大于或等于字符串的长度,则slice()返回一个空字符串。

如果endIndex省略,则将slice()字符提取到字符串的末尾。如果为负,它被视为strLength + endIndex其中strLength是字符串的长度。

var str = 'abcdefghij';
console.log('(1, 2): '   + str.slice(1, 2));   // '(1, 2): b'
console.log('(-3, 2): '  + str.slice(-3, 2));  // '(-3, 2): '
console.log('(-3, 9): '  + str.slice(-3, 9));  // '(-3, 9): hi'
console.log('(-3): '     + str.slice(-3));     // '(-3): hij'
console.log('(-3,-1): ' + str.slice(-3,-1));     // '(-3,-1): hi'
console.log('(0,-1): '  + str.slice(0,-1));     // '(0,-1): abcdefghi'
console.log('(1): '      + str.slice(1));      // '(1): bcdefghij'
console.log('(-20, 2): ' + str.slice(-20, 2)); // '(-20, 2): ab'
console.log('(20): '     + str.slice(20));  // '(20): '
console.log('(20, 2): '  + str.slice(20, 2));  // '(20, 2): '
  • split():把字符串分割为子字符串数组
var stringValue = 'hello world';
console.log(stringValue.split(' ')); // ['hello', 'world']
console.log(stringValue.split('')); // ['h','e', 'l', 'l', 'o', '','w', 'o', 'r','l', 'd']
console.log(stringValue); // 'hello world' 不改变源字符串
  • trim():移除字符串首尾空白,但不能移除中间的空白
var stringValue = ' hello world  ';
console.log(stringValue.trim()); // 'lo world'
console.log(stringValue); // ' hello world  ' 不改变源字符串
  • indexOf()、lastIndexOf():搜索指定的子字符串,返回子字符串的位置,没有找到则返回-1
var stringValue = 'hello world';
console.log(stringValue.indexOf('o'));  //4
console.log(stringValue.lastIndexOf('o')); //7
  • toLowerCase():创建原字符串的小写副本
  • toUpperCase():创建原字符串的大写副本

五、常用数组操作方法

  • join():数组拼接为字符串
var arr = [1,2,3];
console.log(arr.join()); // '1,2,3'
console.log(arr.join('-')); // '1-2-3'
console.log(arr); // [1, 2, 3](原数组不变)
  • push()、pop()

    • push(): 把里面的内容添加到数组末尾,并返回修改后的长度。
    • 移除数组最后一项,返回移除的那个值,减少数组的length。
var arr = ['Lily','lucy','Tom'];
var count = arr.push('Jack','Sean');
console.log(count); // 5
console.log(arr); // ['Lily', 'lucy', 'Tom', 'Jack', 'Sean']
var item = arr.pop();
console.log(item); // Sean
console.log(arr); // ['Lily', 'lucy', 'Tom', 'Jack']
  • shift()、unshift()

    • shift():把数组的第一个元素从其中删除,并返回第一个元素的值
    • unshift():向数组的开头添加一个或更多元素,并返回新的长度
var arr = ['Lily','lucy','Tom'];
var count = arr.unshift('Jack','Sean');
console.log(count); // 5
console.log(arr); //['Jack', 'Sean', 'Lily', 'lucy', 'Tom']
var item = arr.shift();
console.log(item); // Jack
console.log(arr); // ['Sean', 'Lily', 'lucy', 'Tom']
  • sort():将数组里的项从小到大排序
var arr1 = ['a', 'd', 'c', 'b'];
console.log(arr1.sort()); // ['a', 'b', 'c', 'd']

sort()方法比较的是字符串,没有按照数值的大小对数字进行排序,要实现这一点,就必须使用一个排序函数

function sortNumber(a,b)
{return a - b;
}
arr = [13, 24, 51, 3];
console.log(arr.sort()); // [13, 24, 3, 51]
console.log(arr.sort(sortNumber)); // [3, 13, 24, 51]
  • reverse():反转数组
var arr = [13, 24, 51, 3];
console.log(arr.reverse()); // [3, 51, 24, 13]
console.log(arr); // [3, 51, 24, 13]
  • concat():连接两个或多个数组
var arr = [1,3,5,7];
var arrCopy = arr.concat(9,[11,13]);
console.log(arrCopy); // [1, 3, 5, 7, 9, 11, 13]
console.log(arr); // [1, 3, 5, 7]
  • slice(start,end):数组截取
var arr = [1,3,5,7,9,11];
var arrCopy = arr.slice(1);
var arrCopy2 = arr.slice(1,4);
console.log(arrCopy); // [3, 5, 7, 9, 11]
console.log(arrCopy2); // [3, 5, 7]
console.log(arr); // [1, 3, 5, 7, 9, 11]
  • splice(index,howmany):删除、插入和替换

    • 删除:指定 2 个参数:要删除的第一项的位置和要删除的项数。
      书写格式:arr.splice(1, 3)
    • 插入:可以向指定位置插入任意数量的项,只需提供 个参数:起始位置、 0(要删除的项数)和要插入的项。
      书写格式:arr.splice(2, 0, 4, 6)
    • 替换:可以向指定位置插入任意数量的项,且同时删除任意数量的项,只需指定3个参数:起始位置、要删除的项数和要插入的任意数量的项。插入的项数不必与删除的项数相等。
      书写格式:arr.splice(2,0,4,6)
var arr = [1,3,5,7,9,11];
var arrRemoved = arr.splice(0,2);
console.log(arr); // [5, 7, 9, 11]
console.log(arrRemoved); // [1, 3]
var arrRemoved2 = arr.splice(2,0,4,6);
console.log(arr); // [5, 7, 4, 6, 9, 11]
console.log(arrRemoved2); // []
var arrRemoved3 = arr.splice(1,1,2,4);
console.log(arr); // [5, 2, 4, 4, 6, 9, 11]
console.log(arrRemoved3); // [7]

JS常用数据处理方法相关推荐

  1. JS常用属性方法大全

    JS常用属性方法大全 1.输出语句:document.write(""); 2.JS中的注释为: 3.传统的HTML文档顺序是:document->html->(hea ...

  2. 前端JS常用工具方法

    前端JS常用工具方法 // var ua = window.navigator.userAgent.toLowerCase(); /*** 前端JS常用工具方法* @class Tools*/ exp ...

  3. concat合并的数组会有顺序么_超全的JS常用数组方法整理

    前言 常用数组方法汇总 方法解析 1:concat(); 2:join(); 3:pop(); 4:shift(); 5:unshift(); 7:reverse(); 8:sort(); 9:sli ...

  4. 目标检测的常用数据处理方法!

    ↑↑↑关注后"星标"Datawhale 每日干货 & 每月组队学习,不错过 Datawhale干货 作者:徐和鼎,浙江大学,Datawhale优秀学习者 前沿 在上节内容中 ...

  5. 【CV】目标检测的常用数据处理方法!

    作者:徐和鼎,浙江大学,Datawhale优秀学习者 前沿 在上节内容中,我们介绍了目标检测的基础概念,并分析了实现目标检测的常用思路,本篇文章将重点介绍在该领域的经典数据集:VOC数据集,以及使用D ...

  6. js常用四舍五入方法

    常用的四舍五入方法函数有tofixed方法和round方法 1 .tofixed方法 toFixed() 方法可把 Number 四舍五入为指定小数位数的数字.例如将数据Num保留2位小数,则表示为: ...

  7. Node.js 常用Mongoose方法

    Node.js 手册查询-Mongoose 方法 一.Schema 一种以文件形式存储的数据库模型骨架,无法直接通往数据库端,也就是说它不具备对数据库的操作能力.可以说是数据属性模型(传统意义的表结构 ...

  8. js常用工具方法utils

    申明:不是我写的,但是我忘记在那篇文章上找到的 记录下来 /*** 邮箱* @param {*} s*/ export const isEmail = (s) => {return /^([a- ...

  9. Javascript——js常用的方法(一)...........

    push() push() 方法可向数组的末尾添加一个或多个元素,并返回新的长度. 此方法改变数组的长度. 在数组起始位置添加元素请使用 unshift() 方法. 1.push方法是数组中的 var ...

最新文章

  1. 一行命令堆出你的新垣结衣,不爆肝也能创作ASCII Art
  2. 4_Tensorflow框架的使用(20181217-)
  3. Google 出品的 Java 编码规范和编程指南!
  4. JVM学习笔记之-JVM性能监控-JVM监控及诊断工具-GUI方式-Visual VM-JProfiler-Arthas
  5. 2019 Android 高级面试题总结 从java语言到AIDL使用与原理
  6. elementUI vxe-table结合使用(通用表格)
  7. 中国软件20年,向金山和中国软件英雄致敬!
  8. [导入]身份验证方面的问题
  9. node和npm是什么_什么是npm? 面向初学者的Node Package Manager教程
  10. (41)FPGA面试技能提升篇(FC接口、GTX/GTH介绍)
  11. ApiPost V5 升级指南
  12. python和plc哪个难_学习PLC有前途吗?
  13. linux2t硬盘格式化时间,linux下大于2T硬盘格式化方法
  14. Cadence OrCAD Capture 在图纸中添加系统框图的方法
  15. 【SAP Basis】SAP用户权限管理
  16. 爷回青——小米5s Plus刷入LineageOS
  17. Re:从零开始的DS学习之查找算法
  18. PHP+AJAX教程(详细)
  19. java打怪升级代码_1255: 打怪升级(Java)
  20. 仙境传说 v1.0 绿色

热门文章

  1. torch把存放tensor的整个list都转为tensor ValueError}only one element tensors can be converted to Python scal
  2. SpringBoot 优雅实现动态数据源切换配置
  3. 试简介视频编码技术?——知乎大神神回答
  4. Keras的基本介绍
  5. 网络编程--TCP-qq聊天室
  6. IOS Swift 入门学习汇总 (更新中..)
  7. 吴孟达版《高等工程数学》第四章+matlab实践
  8. 使用arduino D1 wifi模块(WeMos D1)连接阿里云物联网平台并成功实现APP点亮板载LED(五)---MQTT.fx模拟设备连接阿里云
  9. python R 实现数字变古诗
  10. ext4数据恢复实战及文件系统结构详解