若是你看完以为没用,欢迎打死兔子(博主)。javascript
parseInt(string, radix)
radix 可选。表示要解析的数字的基数。该值介于 2 ~ 36 之间。 若是省略该参数或其值为 0,则数字将以 10 为基础来解析。若是它以 “0x” 或 “0X” 开头,将以 16 为基数。若是该参数小于 2 或者大于 36,则 parseInt() 将返回 NaN。java
parseInt('10', 2); // 2 1*2^1 + 0*2^0 = 2
parseInt('17', 8); // 15 1*8^1 + 7*8^0 = 15
parseInt('1f', 16); // 31 1*16^1 + 15*16^0 31
parseInt('0x12'); // 18 1*16^1 + 2*16^0 = 18
复制代码
number.toString(radix)
radix 可选。规定表示数字的基数,是 2 ~ 36 之间的整数。若省略该参数,则使用基数 10。可是要注意,若是该参数是 10 之外的其余值,则 ECMAScript 标准容许实现返回任意值。数组
var num = 15;
num.toString(2); // 1111 1*2^3 + 1*2^2 + 1*2^1 + 1*2^0 = 15
num.toString(8); // 17 1*8^1 + 7*8^0 = 15
num.toString(16); // f f在16进制中即表明15(0~9,A~F)
复制代码
var num = 1;
num.toString(); // "1"
Number(1).toString(); // "1"
1.toString(); // Uncaught SyntaxError: Invalid or unexpected token
1.0.toString(); // "1"
1..toString(); // "1"
1 .toString(); // "1"
复制代码
缘由:当点跟在一个数字后面就意味着这个数字是一个浮点数,在点后面JS等待着一个数字。 因此在调用toString()
以前,咱们须要告诉JS这是就是咱们要的数字。经过变量的形式调用toString()
,其实是发生了隐式转换,number
属于基本类型,是没有toString()
方法的,隐式转换变为包装类型,因此不会报错。安全
解答:对于计算机而言,两个数字在相加时是以二进制形式进行的,在呈现结果时才转换成十进制。这样的结果是由于在转换的过程当中发生了精度丢失,解决的办法是先转换为整数执行操做后再降下来,固然对于复杂的,能够引入第三方库(bignumber.js等)。ide
Number.MAX_VALUE; // 1.7976931348623157e+308
Number.MIN_VALUE; // 5e-324
复制代码
这里的迭代方法有: every() 、 filter() 、 forEach() 、 map() 、 some() 、 find() 、 findIndex() 。
这些方法的所需参数都相同,以用的最多的forEach()
为例进行说明:函数
array.forEach(function(currentValue, index, arr), thisValue)
thisValue 可选。传递给函数的值通常用 "this" 值。若是这个参数为空, "undefined" 会传递给 "this" 值post
function run(param) {
console.log( param, this.id );
}
var obj = {
id: "welcome"
};
[1, 2, 3].forEach( run, obj ); // 1 "welcome" 2 "welcome" 3 "welcome"
复制代码
若是须要在迭代中显示绑定this
,不妨考虑下这个第二参数。ui
array.reduce(function(total, currentValue, currentIndex, arr), initialValue)
①function(total,currentValue, index,arr)this
- total 必需。初始值, 或者计算结束后的返回值。
- currentValue 必需。当前元素
- currentIndex 可选。当前元素的索引
- arr 可选。当前元素所属的数组对象。
②initialValue 可选。传递给函数的初始值spa
var str = 'welcome to my world';
var obj = {};
[...str].reduce((prev, cur)=>{
obj[cur] ? obj[cur]++ : obj[cur] = 1;
}, {})
console.log(obj); // {" ": 3,c: 1,d: 1,e: 2,l: 2,m: 2,o: 3,r: 1,t: 1,w: 2,y: 1}
复制代码
以定义对象的形式来定义数组,以下:
var arr = {
0: 1,
1: 2,
2: 3,
length: 3
}
arr[0]; // 1
typeof arr; // "object"
复制代码
数组是特殊的对象,天然能够添加属性:
var arr = [1, 2, 3];
arr.md = 'well';
arr.length; // 3
arr.md; // "well"
// 注意点
arr["2"] = 4; // 这里有引号,本质上就算这里没有引号,也会先转成字符串形式,由于对象的键只能为字符串
arr[2]; // 4
复制代码
string.slice(start,end) 参数能够为负数
string.substr(start,length) 第一参数可为负数,第二参数为长度
string.substring(from, to) 参数都必须为非负整数
做用:第三参数会做为第一个函数的参数传入
for(var i = 0; i<6; i++){
setTimeout(function(){
console.log(i);
},1000);
} // 输出6次6
for(var i=0;i<6;i++){
setTimeout(function(j){
console.log(j);
},i*1000,i);
} // 依次输出0~5,间隔为1秒
复制代码
- 若是第一个操做数是对象,则返回第二个操做数;
- 若是第二个操做数是对象,则只有在第一个操做数的求值结果为 true 的状况下才会返回该 对象;
- 若是两个操做数都是对象,则返回第二个操做数;
- 若是有一个操做数是 null,则返回 null;
- 若是有一个操做数是 NaN,则返回 NaN;
- 若是有一个操做数是 undefined,则返回 undefined。
undefined + undefined; // NaN (Not a Number)
undefined + null; // NaN
1 + null; // 1 说明:Number(null) 返回 0 isNaN(null) === false
1 + undefined; // NaN 说明:Number(undefined) 返回 NaN isNaN(undefined) === true
'1' + null; // "1null"
'1' + undefined; // "1undefined"
'1' + 1; // "11"
1+ {a:1} // "1[object Object]"
复制代码
在《javaScript高级程序设计》一书"加性操做符"一节中,有很详细的说明,这里摘要三点:
- 若是有一个操做数是 NaN,则结果是 NaN;
- 若是只有一个操做数是字符串,则将另外一个操做数转换为字符串,而后再将两个字符串拼接 起来。
不过,若是有一个操做数是字符串,那么就要应用以下规则:
- 若是两个操做数都是字符串,则将第二个操做数与第一个操做数拼接起来;
- 若是只有一个操做数是字符串,则将另外一个操做数转换为字符串,而后再将两个字符串拼接 起来。
- 若是有一个操做数是对象、数值或布尔值,则调用它们的 toString()方法取得相应的字符串值, 而后再应用前面关于字符串的规则。对于 undefined 和 null,则分别调用 String()函数并取得字符串"undefined"和"null"。
1 == '1'; // true
1 === '1'; // false
NaN == NaN; // false
NaN === NaN; // false
+0 == -0; // true
+0 === -0; // true
null == undefined; // true
null === undefined; // false
复制代码
Object.is() 与之不一样之处:
Object.is(+0, -0); // false
Object.is(NaN, NaN); // true
复制代码
先看 Object.create() 的说明:
Object.create(proto[, propertiesObject])
参数:
proto 新建立对象的原型对象 propertiesObject 可选。若是没有指定为 undefined,则是要添加到新建立对象的不可枚举(默认)属性(即其自身定义的属性,而不是其原型链上的枚举属性)对象的属性描述符以及相应的属性名称。这些属性对应Object.defineProperties()的第二个参数
返回值:
一个新对象,带着指定的原型对象和属性。
Object.create(null) 将返回的新对象的原型设为 null ,相比 {} ,它不会有 Object 对象原型上的如 toString() 等方法,它做为空对象更干净更安全,不少时候用处很大。我喜欢用穷徒四壁来形容 {} ,那么 Object.create(null) 对比之下就是连四壁也没有。
for...in循环遍历对象自身的和继承的可枚举属性(不含 Symbol 属性)。
Object.keys返回一个数组,包括对象自身的(不含继承的)全部可枚举属性(不含 Symbol 属性)的键名。
Object.getOwnPropertyNames返回一个数组,包含对象自身的全部属性(不含 Symbol 属性,可是包括不可枚举属性)的键名。
Object.getOwnPropertySymbols返回一个数组,包含对象自身的全部 Symbol 属性的键名。
Reflect.ownKeys返回一个数组,包含对象自身的(不含继承的)全部键名,无论键名是 Symbol 或字符串,也不论是否可枚举。
遍历规则:
首先遍历全部数值键,按照数值升序排列。
其次遍历全部字符串键,按照加入时间升序排列。
最后遍历全部 Symbol 键,按照加入时间升序排列。
Reflect.ownKeys({ [Symbol()]:0, b:0, 10:0, 2:0, a:0 })
// ['2', '10', 'b', 'a', Symbol()]
复制代码
共有3种方式:
if('key' in obj)
会检测继承属性obj.hasOwnProperty('key')
只检测自身属性if(obj.key)
由于原型链机制,会检测继承属性(对于if
中发生的隐式转换请阅读标题15的内容)注意: 慎用第三种方式,有时这种方式可能达不到你预期的效果。
举例说明:
var myObject = {
a: undefined
};
myObject.a; // undefined
myObject.b; // undefined
复制代码
数据类型 | 转换为true的值 | 转换为false的值 |
---|---|---|
Boolean | true | false |
String | 任何非空字符串 | ""(空字符串) |
Number | 任何非零数字值(包括无穷大) | 0和NaN |
Object | 任何对象 | null |
Undefined | 不适用 | undefined |
new Date().getDay()
返回的是一周中的某一天new Date().getDate()
返回的是一月中的某一天 tips: 开发中总见有人对此混淆
禁止一个对象添加新属性而且保留已有属性,已有属性能够删除
这个方法实际上会在一个现有对象上调用 Object.preventExtensions() 并把全部现有属性标记为 configurable:false。
因此,密封以后不只不能添加新属性,也不能从新配置或者删除任何现有属性(虽然能够 修改属性的值)。
这个方法实际上会在一个现有对象上调用 Object.seal() 并把全部“数据访问”属性标记为 writable:false,这样就没法修改它们的值。
这个方法是你能够应用在对象上的级别最高的不可变性,它会禁止对于对象自己及其任意 直接属性的修改
固然对应的还有解除不变性的方法,这里就不介绍了。
浅拷贝和深拷贝都是相对于Object
, Array
这样的引用类型而言的,由于对基本类型来讲没有意义
引用类型数据在内存中的存储 | ||
---|---|---|
栈内存 | 堆内存 | |
name | val | val |
obj | 堆地址(指向堆内存的值) | {a: 1,b: 2...} |
var a = [1, 2, 3];
var b = a;
b[2] = 4;
console.log(a[2]); // 4
复制代码
var obj = {
a: 1,
b: 2
}
var obj1 = Object.assign(obj);
obj1.a = 3;
console.log(obj.a) // 3
复制代码
var obj = {
a: 1,
b: 2
}
var obj1 = JSON.parse(JSON.stringify(obj));
obj1.a = 3;
console.log(obj.a); // 1
复制代码
var arr = [1, 2, 3];
var arr1 = [...arr];
arr1[2] = 4;
console.log(arr[2]); // 3
复制代码
slice()、concat()
说明:
slice()、concat()
都会返回一个新的数组副本
function deepCopy(a, b= {}) {
for(let item in a){
if(typeof a[item] === "object"){
b[item] = {};
deepCopy(a[item], b[item]);
}else{
b[item] = a[item];
}
}
return b;
}
var a = {
x: 1,
y: {
z: 2
}
}
var b = deepCopy(a);
a.y.z = 4;
console.log(b.y.z); //2 b中属性值并无改变,说明是深拷贝
复制代码
解释:传入的参数,不管它是基本类型仍是引用类型,把握一个原则,按 "值" 传递。理解就是把函数外部值拷贝一份,而后把拷贝的值赋值给内部参数,这里的拷贝特指浅拷贝,因此这里拷贝的值分两种状况:
var type = 'images';
var size = {width: 800, height: 600};
var format = ['jpg', 'png'];
function change(type, size, format){
type = 'video';
size = {width: 1024, height: 768};
format.push('map');
}
change(type, size, format);
console.log(type, size, format); // 'images', {width: 800, height: 600}, ['jpg', 'png', 'map']
复制代码
for > forEach() > map()
缘由:forEach() 与 map() 遍历须要维护当前项和索引,必然要比 for 慢,而 map() 会分配内存空间存储新数组并返回,forEach() 不会返回数据,因此 map() 最慢 。
parentClass.prototype.constructor.call(this)。
class A {}
A.prototype.x = 2;
class B extends A {
constructor() {
super();
}
print(){
console.log(super.x);
}
}
var b = new B();
b.print(); // 2
复制代码
class A { // 阮老师的例子
constructor() {
this.x = 1;
}
static print() {
console.log(this.x);
}
}
class B extends A {
constructor() {
super();
this.x = 2;
}
static m() {
super.print();
}
}
B.x = 3;
B.m() // 3
复制代码
若是对最后一个程序心存疑惑,能够去看个人这篇《你不知道的JS系列——全面解析this》。
小朋友,你在看到上面一个一个的标题的时候,是否有不少问号???
若是有,那证实基础还需增强。