Author:
bugall
Wechat:bugallF
Email:769088641@qq.com
Github: https://github.com/bugalljavascript
空值(null) 未定义(undefined) 布尔值(boolean) 数字(number) 字符串(string) 对象(object) 符号(symbol,ES6新增)
typeof null === 'object' //true 正确的返回结果应该是"null",但这个bug由来已久, 在javascript中已经存在了将近20年,也许永远也不会修复 由于这涉及太多现有的web系统,修复它会产生更多的bug
var a = null; (!a && typeof a === "object"); //true
实际上function是object的一个“子类型”, 函数是"可调用对象",它有一个内部属性[[Call]], 该属性使其能够被调用
typeof [1,2,3] === "object"; //true
变量能够随时持有任何类型的值
变量在做用域中声明可是没有复制为"undefined", 变量在做用域中未声明"undeclared"
使用delete运算符能够将单元从数组中删除, 可是单元删除后数组的length属性并不会发生变化
var a = []; a[0] = 1; a[2] = 3; a[1]; //undefined a.length; //3
var a = []; a[0] = 1; a["bugall"] = 2; a.length; //1 a["bugall"] = 2; a.bugall = 2;
var a = []; a["13"] = 42; a.length; //14
javascript中的数字类型是基于IEEE 754标准实现的, 该标准一般也被称为“浮点数”,javascript使用的是 "双精度"格式64位二进制
42..toFixed(2) = 42.00,42.toFixed(2) 是无效语法,由于.被视为常量42.的一部分
二进制浮点数中0.1和0.2并非十分精确,它们相加的结果并不是恰好等于0.3,而是一个 很是接近的数字0.3000000000000000002
function numbersCloseEnoughToEqual(n1,n2){ return Math.abs(n1-n2)<Number.EPSILON } numbersCloseEnoughToEqual(0.3,0.3) //true
数字的呈现方式决定了“整数”的安全值范围远远小于 Number.MAX_VALUE,最大是2^53-1
Number.isInterger(42) //true Number.isInterger(42.000) //true Number.isInterger(42.001) //false
undefined类型只有一个值,即undefined, null类型也只有一个值,即null,它们的名称是类型也是值
若是数学运算的操做不是数字类型,就没法返回一 个有效的数字,这种状况下返回值为NaN
var a = 2 / "foo" //NaN typeof a === "number" //true
NaN是执行数学运算没有成功返回的结果, NaN是一个特殊值,它和自身不相等,是惟一一个非自反的值 NaN != NaN //true
前者一直是我错误的理解,正确的理解应该是is NaN, 判断数学运算是否错误,返回错误的值
var a = 2 / "foo" var b = "foo" a; //NaN b; //"foo" isNaN(a) //true isNaN(b) //true 这是不一样的结果,一个是运算出错,一个是字符串
代码中尽量得少出现isNaN()
null,undefined,string,number,boolean
咱们没法更改使用值传递仍是引用传递,一切根据值的类型肯定
function a(){...} //函数声明 var a = function(){...} //函数表达式
(function foo(){ var a=3; console.log(a) //3 })() 因为函数被包含在一对()括号内部,所以成为一个函数表达式, 经过在末尾加上另外一个()能够当即执行这个函数。 第一个()将函数变成表达式
console.log(a) //undefined var a = 3; console.log(a) //3
console.log(a) //undefined if(false){ var a = 3; }
{ console.log(a) //ReferenceError var a = 3 console.log(a) //3 }
foo() //bugall function foo(){ console.log('bugall') } a() // ReferenceError var a = foo(){ console.log('bugall') }
function a(){ var n = 'bugall' function b(){ console.log(n) } return b } foo() //'bugall' 觉得b()覆盖了a()里的变量n,因此a的资源就没法释放,而这个引用就叫作闭包
var obj = { name = 'bugall', sayName = function(){ console.log(this.name) }) } var name = 'not bugall' obj.cool() //bugall ,this的做用域是obj对象 setTimeount(obj.cool,100) //not bugall,this变成了当前做用域 用this的形式 var obj = { name = 'bugall', sayName = function(()=>{ console.log(this.name) }) } var name = 'not bugall' obj.cool() //bugall ,this的词法做用域是obj setTimeount(obj.cool,100) //bugall, this的词法做用域没有变
function foo(){ foo.count = 4; //foo指向自身 } setTimeout(function(){ //匿名函数由于没有名字,没法指定在堆栈上得肯定位置,因此不能引用自身 })
function foo(){ console.log(this.a) } var a = 2 foo() //2
function foo(){ 'use strict' console.log(this.a) } var a = 2 foo() //TypeError: this is undefined
function foo(){ console.log(this.a) } var obj2 = { a:42, foo:foo } var obj1 = { a:2, obj2:obj2 } obj1.obj2.foo() //42
function foo(){ console.log(this.a) } var obj = { a:2 } foo.call(obj) //2 咱们在调用foo的时候强制把它的this绑定到obj上
function foo(something){ console.log(this.a,somethis) return this.a + something } var obj = { a:2 } var bar = foo.bind(obj) var b = bar(3) // 2 3 console.log(b) //5 bind(...)会返回一个硬编码的新函数, 它会把你指定的参数设置为this的上下文并调用原始函数
在javascript中,构造函数只是一些使用new操做符 时被调用的函数,他们并不会属于某个类,也不会实例化一个类, 实际上它们甚至都不能说是一个特殊的函数类型,他们只是 被new操做符调用的普通函数而已。 使用new来调用函数的时候,会自动执行下面的操做 1. 建立(或者说构造)一个全新的对象 2. 这个新对象会被执行[[prototype]]链接 3. 这个新对象会被绑定到函数调用的this 4. 若是函数没有返回其余对象,那么new表达式中的函数调用会自动返回这个新对象
function foo(a){ this.a=a } var bar = new foo(2) console.log(bar.a) //2
function foo(){ console.log(this.a) } var obj1 = { a:2, foo:foo } var obj2 = { a:3, foo:foo } obj1.foo() //2 obj2.foo() //3 obj1.foo.call(obj2) //3 obj2.foo.call(obj1) //2
function foo(somethis){ this.a = somethis } var obj1 = { foo:foo } var obj2 = {} obj1.foo(2) console.log(obj1.a)//2 obj1.foo.call(obj2,3) console.log(obj2.a) //3 var bar = new obj1.foo(4) console.log(obj1.a) //2 console.log(bar.a) //4 bar被绑定到obj1上,可是new bar(3)并无像咱们预期的那样把obj1.a修改成3 相反,new修改了硬绑定(到obj1的)调用bar(...)中的this,由于使用了new绑定获得 一个名字为baz的新对象,而且baz.a的值是3
call,apply属于显示绑定 bind属于硬绑定,硬绑定属于显示绑定的一种
硬绑定会下降函数的灵活性,使用硬绑定以后就 没法使用隐式绑定或是显式绑定来修改this
1. 函数是否在new中调用(new绑定),若是是的话this绑定的是新建立的对象 var bar = new foo() 2. 函数是否经过call,apply(显示绑定)或者硬绑定调用, 若是是的话,this绑定的是指定的对象 var bar = foo.call(obj2) 3. 函数是否在某个上下文对象中调用(隐式绑定),若是是的话,this绑定的是那个上下文对象 var var = obj1.foo() 4. 若是都不是的话,使用默认绑定,若是在严格模式下,就绑定到undefined,不然绑定到全局对象 var bar = foo()