JavaScript基础(一)
-
数据类型
原始类型:number boolean null undefined string symbol(es6新增表示独一无二的)
对象类型:object -
类型转换
原始值 | 转换目标 | 结果 | 方法 |
---|---|---|---|
number | 布尔 | 除0,-0,NaN外都为true | boolean()或使用 !!原始值 |
undefined null | 布尔 | false | boolean()或使用 !!原始值 |
string | 布尔 | 除空串外都为true | boolean()或使用 !!原始值 |
引用类型 | 布尔 | true | boolean(),boolean()或使用 !!原始值 |
null | 数字 | 0 | 原始值+0 |
数组 | 数字 | 空数组为0,非空则为数组元素,其他为NaN | 原始值+0 |
除数组外的引用类型 | 数字 | NaN | 原始值+0 |
string | 数字 | ‘1’->1,‘a’-> NaN | 原始值+0 |
布尔 函数 symbol | 字符串 | ‘true’ | toString(),windows.string(),原始值+’’ |
对象 | 字符串 | ‘[object Object]’ | toString(),windows.string(),原始值+’’ |
-
变量赋值与函数参数传递
变量赋值
原始类型(数值、字符串、布尔),赋值方式是传值,意味着修改被赋值的变量,不会改变原始值a=5; b=a; //b=5 b=3; console.log(b); //3 console.log(a); //5
引用类型(数组、对象),赋值的方式是穿址,意味着修改被复制的对象,会改变原始值
a=[4,5,6]; b=a; // b=[4,5,6] b[0]=1; console.log(b); //b=[1,5,6] console.log(a); //a=[1,5,6]
如果是修改整个被复制的对象,也不会改变原始值
a =[4,5,6]; b=a; // b=[4,5,6] b=[1,2,3]
在上例,赋值后,b是指向a的,重新给b赋值,b会全部指向数组[1,2,3],所以b的改变不会引起a的改变
针对以上情况,可以使用Object.assign来解决问题,该方法只会拷贝所有的属性值到新对象中,如果属性值是对象,拷贝的是地址,该方法称为浅拷贝
let a = { age: 1 } let b = Object.assign({}, a) a.age = 2 console.log(b.age) // 1
也可使用展开运算符…实现浅拷贝
let a = { age: 1 } let b = { ...a } a.age = 2 console.log(b.age) // 1
浅拷贝只解决了第一层问题,如果接下去的值中还有对象的话,那么就必须使用深拷贝,JSON.parse(JSON.stringify(object))
let a = { age: 1, jobs: { first: 'FE' } } let b = JSON.parse(JSON.stringify(a)) a.jobs.first = 'native' console.log(b.jobs.first) // FE
函数参数传递
函数参数如果是原始类型的值(数值、字符串、布尔值),传递方式是传值传递。这意味着,在函数体内修改参数值,不会影响到函数外部。var p=1; function f(p) { p=3 } f(p); p; // 1
如果传递的是引用类型(数组、对象),传递方式是传址,也就是说传递的是原始值的地址,因此在函数内部修改参数,会影响原始值。
var obj={p:1}; function f(o){ o.p=2 } f(obj) obj.p //2
如果在函数内部修改,是替换整个参数,这时不会影响到原始值
var obj=[1,2,3]; function f(p){ p=[4,5,6]; } f(obj); obj // [1,2,3]
在上例中,参数对象obj被全部替换成另一个值[4,5,6],由于形式参数p的值实践上是参数obj的地址,,重新对p赋值导致p指向另一个([4,5,6])地址,保存在原地址上的值当然不受影响。
-
闭包
JavaScript两种作用域:全局作用域和函数作用域。函数内部可以直接读取全局变量,但函数外部无法读取函数内部声明的变量.如果我们要读取函数内部声明的变量,需要在函数内部再定义一个函数function f1(){ var n=88; function f2(){ console.log(n); //88 } return f2; } var result =f1(); result(); //88
f1的返回值是函数f2,这样就可以在外部获取f1的内部变量n,其中f2函数就是闭包,及就是能够读取其他函数内部变量的函数,闭包就是将函数内部与函数外部连接起来的一座桥梁。
闭包的另一个作用,使得变量始终保持在内存中,
function createIncrementor(start) { return function () { return start++; }; } var inc = createIncrementor(5); inc() // 5 inc() // 6 inc() // 7
闭包的使用,使得当前作用域可以访问外部作用域成为可能,及thid指向全局对象。但也可以使用bind,apply,call来绑定对象
var name = "The Window"; var object = { name : "My Object", getNameFunc : function(){ return (function(){ alert(this.name); }.bind(object))(); }, getName:function(){ alert(this.name); } }; object.getNameFunc(); //My Object object.getName(); //My Object
注:apply call bind函数各参数及格式
函数 格式 call call(绑定对象,字符串1,字符串2) bind bind(绑定对象,字符串1,字符串2) () apply apply(绑定对象,[字符串1,字符串2]) -
this
它是函数运行时,在函数体内部自动生成的一个对象,只能在函数体内部使用。函数的不同使用场合,this有不同的值。总的来说,this就是函数运行时所在的环境对象
例题var name = "The Window"; var object = { name : "My Object", getNameFunc : function(){ var that = this;//此行中this指向的环境是 object下 return function(){ return that.name; // this指向的环境是 object下,that也是在object下 }; } }; alert(object.getNameFunc()());//My Object var name = "The Window"; var object = { name : "My Object", getNameFunc : function(){ return function(){ return this.name; // this指向的环境是 windows }; } }; alert(object.getNameFunc()());//The Window