- null
console.log([typeof null, null instanceof Object])
// ['object', false]
/*
A instanceof B 判断对象A的原型链上是否有B的原型
null 没有原型
*/
- 隐式类型转换
[]['map'] + [1,2] // 'function map(){}1,2'
//加号两个作用:拼接,相加; 有引用数据类型和字符串的都是拼接
//======================================================
[]['a'] + [1,[2,3]] // 'undefined1,2,3'
//======================================================
[]['push'](1) // 1
// push 返回的结果是变换后数组的长度
//=======================================================
(![]+[])[+[]] // 'f'
// ! 取反, 隐式类型转换
// (false + [])[0] ==> ('false')[0] ==> 'f'
//=======================================================
(![] + [])[+!![]] // 'a'
// (false + [])[+true]
//=======================================================
++[[]][+[]] + [+[]] // '10'
// ++ [[]][0] + [0] ==> ++[] + [0] ==> 1 + [0]
//=======================================================
[1<2<3, 3<2<1] // [true, true]
- 函数提升
var a = 1,
b = c = 0;
function add(n) {
return n += 3
}
y = add(a); // 5
function add(n) {
return n *= 5;
}
z = add(a); // 5
console.log(y, z)
// 函数会先提升的最前面,后面的函数会覆盖前面的
- 字符串对象
function showCase(value) {
switch (value) {
case 'A':
console.log('a');
break;
case 'B':
console.log('B')
break;
case undefined:
console.log('undefined');
break;
case new String('A'):
console.log(new String('A'));
break;
default:
console.log('default')
}
}
showCase(new String('A')) //'default'
// new String('A') 返回一个对象,内存地址不同,执行default
// switch case 中是 === 不是 ==
- 进制转换
parseInt(3,8) // 3
parseInt(3,2) // NaN
parseInt(3,0) // 3
// 后面一位是进制;进制范围[2,36],超过返回NaN; 0默认是10进制
// parseInt 返回10进制结果
- map & 进制
['1', '2', '3'].map(parseInt) // [1, NaN, NaN]
// map 两个参数(当前值和索引)
// 上面等价 parseInt('1', 0) parseInt('2', 1) parseInt('3', 2)
- 实参列表
function fn(ary) {
ary[0] = ary[2]; // ary: [1,1,10] => [10, 1, 10]
}
function bar(a, b, c) {
c = 10;
fn(arguments); // arguments:[1,1,10]
return a + b + c;
}
console.log(bar(1, 1, 1)) // 21
- 数组原型
console.log(Array.isArray(Array.prototype)) // true
(function() {
var x = y = 1
})()
console.log(y) // 1
console.log(x) // 报错
- 隐式数据类型转换
var result = false === 1;
console.log(result) // false
// ==================================
typeof c && -true + (+undefined) + '' // 'NaN'
// 'undefined' && -1 + NaN + '' ==> 'undefined' && 'NaN' => 'NaN'
// ===================================
!!' ' + !!'' - !!false || console.log('go die')
// true + false - false || console.log('go die') ==> 1 || console.log('go die') ==> 1
- this 指向
var length = 10;
function fn() {
console.log(this.length); // 10
}
var obj = {
length: 5,
method: function() {
console.log(this.length); // 5
fn();
arguments[0](); // 2 this指向arguments
}
}
obj.method(fn, 1)
var a = { n: 1 }
var b = a;
a.n = a = { m: 1 }
console.log(a, b) // { m: 1 } {n: {m:1}}
/*
a = 地址1
b = 地址1
a = {m:1} 地址1.n = 地址1 = {m:1} ==> b.n = {m:1}
*/
/*
a = {n:1}
b = {n:1}
a = {m:1}
{n:1}.n = {m:1} == > b.n = {m:1}
*/
var x = 1
if (function fn() {}) {
x += typeof fn
}
console.log(x) // '1undefined'
/*
判断语句等价于 b = function fn() {}
函数表达式没有名字
*/
typeof undefined === typeof Undefined // true
- 包装类销毁
var str = typeof typeof { 'name': 'doudou' } // 'string'
if (str.length == 6) {
str.prop = '12'
}
console.log(str.prop) // undefined
var x = 10;
function a() {
y = function() {
x = 2
}
console.log(this); // window
return function() {
var x = 3;
y();
console.log(this.x); // 2
}.apply(this)
}
a();
console.log(y); // function(){ x = 2}
if (!('a' in window)) {
var a = 1;
}
alert(a) // undefined
// var 变量提升; 'a' 在全局; if(false) 不执行
var n = 10;
var obj = {
n: 5,
c: a()
};
function a() {
var n = 7;
var c = function() {
var n = 3;
console.log(this.n) // 5
}
return c;
}
obj.c(); // this -> obj
var arr = [1, 3, 5, 7, 9]
function fn() {
this.arr = [2, 4, 6, 8, 10]
arr.forEach(function() {
console.log(this.arr) // 回调函数this指向window
})
}
new fn(); // [1,3,5,7,9] 打印5次
- 闭包
function test() {
var n = 4399;
function add() {
n++;
console.log(n)
};
return {
n,
add
}
}
var result1 = test();
var result2 = test();
result1.add(); // 4400
result1.add(); // 4401
console.log(result1.n); // 4399
result2.add(); // 4400