变量命名
变量名:字母 数字 下划线 美元符$
jquery: $ $.each() $ === jQuery
underscore( js的一个函数库) : _ _.each()
关键字 : if for
保留字 : class
推荐有意义的命名:
buttonCancel button_cancel btnCancel
数据类型和堆栈
基本类型(可以修改) : 4 str true undefined null
引用类型(不能修改) : { } [ ]
var score = 40; score = 50;
上面属于覆盖,不属于修改
var str = "hello"; var newStr = str.replace("h", ""); document.write( str + "/" + newStr);
字符串操作返回新的字符串,原字符串没有改变
var obj = {}; console.log(obj); obj.name = "cyy"; obj.age = 25; obj.name = "cyy2"; delete obj.age; console.log(obj);
引用类型的属性可以添加,可以修改,可以删除
var name = "cyy"; name.age = 25; console.log(name.age);//undefined
基本类型不能添加属性
str.replace()
1->Number
"str"->String
不是基本类型有属性和方法,而是通过基本类型找到其包装对象,包装对象会把属性和方法借给该基本类型的变量
基本类型保存在栈内存中,按值访问(直接访问)
引用类型保存在堆内存中,但是地址保存在栈内存中,按引用访问(需要中转)
变量比较和值的赋值
var obj1 = { age: 24, num: 1 } var obj2 = { age: 24, num: 1 } console.log(obj1 === obj2);//false
基本类型的比较就是值的比较,只要值相等即为相等
引用类型,实际上是开辟了各自的内存空间,虽然内容相等,但是并不是一个地址
只有当指向同一个引用的时候,才为相等
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <script> var obj1 = { age: 24, num: 1 } var obj2 = obj1; console.log(obj1 === obj2);//true </script> </body> </html>
此时obj2保存的是obj1的地址,因此相等
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <script> var obj1 = { age: 24, num: 1 } var obj2 = { age: 24, num: 1 } function equelObj(a, b){ for(var i in a){ if(a[i] !== b[i]) return false; } return true; } console.log(equelObj(obj1, obj2));//true </script> </body> </html>
以上方式可以比较两个对象的内容是否相等
function equelArr(a, b){ if(a.length !== b.length) return false; for(var i=0; i<a.length;i++){ if(a[i] !== b[i]) return false; } return true; }
以上方式比较两个数组的内容是否相等
var name1 = "cyy"; var name2 = name1; console.log(name2);//cyy name2 = "cyy2"; console.log(name1);//cyy
基本类型复制是值的复制,两个变量互不干涉
var obj1 = { name: "cyy", age: 24 } var obj2 = obj1; obj2.age++; console.log(obj2.age);//25 console.log(obj1.age);//25
引用类型复制是地址的复制,二者指向同一个地址,一个改变另一个也会发生改变
var obj1 = { name: "cyy", age: 24 } function copyObj(a){ var newObj = {}; for(var i in a){ newObj[i] = a[i]; } return newObj; } console.log(copyObj(obj1));
以上方法是复制一个对象的内容,但不是引用的同一个地址
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <script> var obj1 = { name: "cyy", age: 24, hobby: [] } function copyObj(a){ var newObj = {}; for(var i in a){ newObj[i] = a[i]; } return newObj; } console.log(copyObj(obj1)); </script> </body> </html>
该方式属于浅拷贝,如果对象中某个属性本身是引用类型,则复制时又会该属性又会指向同一个地址,需要用到递归解决
jquery 中的 $.extend 既可以进行浅拷贝,又可以进行深拷贝
不使用新的变量,来对换两个变量的值
var a = 3; var b = 4; a = a + b; //a=7 b = a - b; //b=3 a = a - b; //a=3
一个很奇葩的规则:赋值才会改变引用的地址,但是添加与修改内容不会改变地址
var a=[4]; var b=a;//此时b与a指向同一个空间 a=[4] b=[4] a=[4,44];//此处a被重新赋值,指向了另一个空间;b仍旧指向原来的空间 console.log(a);//(2) [4, 44] console.log(b);//[4] a=b;//此时a又指向了b的空间 a=[4] b=[4] b.push(44); console.log(a);//(2) [4, 44]
参数传递和类型检测
function add(a,b){ return a+b; } console.log(add(3,4));//7
a,b是形参,3,4是实参
function addName(obj){ obj.name="cyy"; } var me={}; addName(me); console.log(me.name);//cyy
引用类型的参数传递(实质上也是值传递)
function addName(obj){ obj.name="cyy";//me.name=cyy(值传递) obj={};//obj指向了一个新的地址,但是me依旧指向老的地址 obj.name="cyy2";//对新的地址进行操作 } var me={}; addName(me); console.log(me.name);//cyy
以上证明:由于引用类型作为参数时,实质上也是值传递。因此当形参被指向新的地址时,并没有对实参进行操作,因为二者并不是指向同一个地址
typeof 检测数据类型,返回值都是字符串类型
数组和对象都是返回object
instanceof Array 判断是否是数组的实例
instanceof Object 判断是够是object的实例(数组也是Object的实例,所有东西都是object的实例)
console.log([] instanceof Array);//true console.log({} instanceof Array);//false console.log([] instanceof Object);//true console.log({} instanceof Object);//true
不用第三个参数,对换两个引用类型的变量值
var a = {name: 'xm'}, b = [4]; a=[a,b];//[{name: 'xm'}, 4] b=a[0];//b={name: 'xm'}; a=a[1];//a=[4]
null是Null类型,属于基本类型
console.log(typeof null);//object console.log(null instanceof Object);//false