1、数据类型
js是弱类型,定义变量时不需要指定具体的数据类型,因此会出现一些奇妙的事情:
var num=23; ---number类型
num="23"; ---string类型
"23" + 23 ; 结果为2323,string类型[字符串的连接
"23" - 23 结果为0,number类型[如果有一个操作数是字符串,先将其转换为数值,再执行减法运算]
六种数据类型:
1)原始类型:number、string、boolean、undefined、null
2)对象:object( Function、Array、Date...)
2、隐式类型转换
若要将string->number : - 0 (减去 0)
number -> string : + '' (加上空串'')
3、包装对象
var str = "string" ; ---string类型
var strObj= new String(" string" ); ---String类型
为什么string类型可以有属性(如length)? 因为在调用时系统自动将其转换为object类型,结束后销毁(还原)
4、类型检测
1) typeof
2) instanceof ---obj instane Object
[2,3] instanceof Array === true
3) Object.prototype.toString
Object.prototype.toString.apply([]) === "[objectArray]"
4)constructor
5) duck type 适用参考来源 类型转换超难【不会】例子
5、运算符 来源
1) ,逗号运算符:从左往右依次运算,结果为最右边的运算值
2) delete运算符:删除值
3) in/
6、语句
1) 在for(var i=0)中定义的i是全局变量,不是块级作用域
2) try catch/finally
3) 函数声明: var fun=function(){ ...//} function fun(){ ...//变量提升,会 先执行 }
4) for in 受原型链影响: var p; var obj={x:1 , y:3}; for( p in obj)
5) with 修改作用域
6) 'use strict' 严格模式
7、对象
1)定义
方式一: var obj={x:1 ,y:2 ,z:{a:1 ,b:2} };
方式二( new/原型链 )
2)对象结构
3)原型链:当定义一个函数(function fun),都会自动有一个原型属性(prototype)
当定义一个新的对象时,在本对象查找不到属性,会沿着原型链往上查找
方式三( Object.create): var obj=Object.create({x:1 ,y:2});
4)属性操作 : 读写对象属性、属性异常、删除属性、检测属性、枚举属性
<1>属性读写方式一:
var obj={x:2 ,y:3};
obj.x; --2 //两种方式
obj["y"]; ---3
<2>属性读写异常
<3>属性删除:delete obj.x ;
<4>属性检测:son in obj ; ---返回true/false (会沿着原型链向上查找)
obj.hasOwnProperty(" son"); ---自身对象
obj.propertyIsEnumberable(" son"); ---是否可以被枚举
Object.defineProperty( obj , "son" ,{ enumerable : true ,value : 23} ); ---定义属性和原型链上的属性
-obj.hasOwnProperty(" son"); ---自身对象
obj.propertyIsEnumberable(" son"); ---是否可以被枚举
Object.defineProperty( obj , "son" ,{ enumerable : true ,value : 23} ); ---定义属性和原型链上的属性 参数:对象,属性,原型链上的属性
一知半解:移驾
属性读写方式二:getter/setter
var person={ name:"cheng" ,get age(){ return 23;} ,set age(val){ ..} };
console.log(person.age); ---23 自动调用get age()方法
5)属性标签:
Object.getOwnPropertyDescriptor( { obj: ' test'} , "obj" ) ; ---参数: 对象,属性
对象标签:[[ proto ]] 、[[ class ]] 、[[ extensible ]]
<1>原型标签 [[ proto ]]
<2>对象类型标签[[ class ]]
var toString=Object.prototype.toString;
function getType(obj){ return toString.call(obj).slice(8,-1); }
//调用获取对象类型的方法,并截取其中的有效数据 , 从第8位开始倒数第2位(去掉[object ])
toString.call(null); ---"[object Null]"
getType(null); ---"Null"
getType(1); ---"Number"
<3>对象(的属性)可扩展标签 extensible
object.preventExtensible(obj); //使obj对象不可新增属性,原属性可改、可删 Object.seal(obj); //使obj不可新增属性,原属性可改但不可删 Object.freeze(obj); //使obj不可新增属性,原属性不可更改、删除
var obj={ x:1 ,y: true ,z: [1,2,3] ,t: undefined }; JSON.stringify(obj); //将js对象序列化---后端 可用
// "{ "x" :1 , "y" :true ,"z" :[1,2,3] } " --undefined直接被舍弃
obj=JSON.parse( '{"x":1 }' ); // obj.x=1 ,将字符串转化为js对象
var obj = { x : 1, y : 2, o : { o1 : 1, o2 : 2, toJSON : function () { return this.o1 + this.o2; } } }; JSON.stringify(obj); // "{"x":1,"y":2,"o":3}"
8、数组
1)值的有序集合。弱类型,每个值可以是不同的类型。也可以是数组
var obj=[ 1, null ,true ,[3,2] ]; ---obj[3][1]=2
2)创建:
var arr=[1,,3]; var arr=[1,,]; ---空为undefined ,默认最后一个可为, var arr2 = new Array(100); ---创建100个空值数组 var arr2 = new Array(1,2,3) ; ---值为1,2 ,3
3)读写
var arr=[1,3];
arr[2]=true; ---动态添加第三个数true
arr.length=3;
delete arr[0]; --删除第一个数据,变为空值"",数组长度不变
arr.length-=1; //通过将数组长度-1,可以动态删除最后一个数据
arr.push(23); 最后位置插入一个值23
var lastNum=arr.pop(); 最后一位数据删除并返回
arr.unshift(23); 首部位置插入一个值23
var firstNum=arr.shift(); 第一位数据删除并返回
4)二维数组
var arr=[[1,2],[2,3],[3,4,5]]; for(var i=0;i<arr.length;i++){ var arr2=arr[i]; for( var j=0;j<arr2.length;j++){ console.log(arr2[j]); } }
5)稀疏数组:不含有从0开始的连续索引,一般length值比实际元素个数大
var arr1 = [undefined]; var arr2 = new Array(1); 0 in arr1; // true var arr=[,,]; 0 in arr2; // false 0 in arr; //false arr1.length = 100; arr1[99] = 123; 99 in arr1; // true 98 in arr1; // false
6)数组方法--原型方法 Object.prototype
var arr=[1,2,3];
arr.join("_"); ---转化为字符串,有参数则为连接符 :1_2_3 ;无参即为 1,2,3
例:function repeatString(str, n) { //快速定义一个重复数组的字符串 return new Array(n + 1).join(str); //长度为n+1,中间的连接为n个 } repeatString("a", 3); // "aaa" [undefined,undefined,undefined,undefined] repeatString("Hi", 5); // "HiHiHiHiHi"
arr.reverse(); ---反序排列数组 : 3,2,1 (原数组被修改)
arr.sort(); ---字母顺序排序
var arr = ["a", "d", "c", "b"];
arr.sort(); // ["a", "b", "c", "d"]
arr = [13, 24, 51, 3];
arr.sort(); // [13, 24, 3, 51]
arr; // [13, 24, 3, 51] ---将第一个去做了比较
arr.sort(function(a, b) { //自定义排序函数 //带参数的排序w3c来源
return a - b;
}); // [3, 13, 24, 51]
arr = [{age : 25}, {age : 39}, {age : 99}];
arr.sort(function(a, b) {
return a.age - b.age;
});
arr.forEach(function(item) {
console.log('age', item.age);
}); // result: age 25、age 39、age 99
arr.concat(2,3); --数组合并
var arr = [1, 2, 3]; arr.concat(4, 5); // [1, 2, 3, 4, 5] arr; // [1, 2, 3] ---原数组没有被修改 arr.concat([10, 11], 13); // [1, 2, 3, 10, 11, 13] --参数是数组,会被拉平一次 arr.concat([1, [2, 3]]); // [1, 2, 3, 1, [2, 3]
arr.slice(2,5); --数组截取 ,参数为索引, [2,5) ,最后一位索引也是 -1
var arr = [1, 2, 3, 4, 5]; arr.slice(1, 3); // [2, 3] --原数组没有被修改 arr.slice(1); // [2, 3, 4, 5] arr.slice(1, -1); // [2, 3, 4] arr.slice(-4, -3); // [2]
arr.splice(2); --数组拼接/删除
var arr = [1, 2, 3, 4, 5]; var arr2 = arr.splice(2); // returns [3, 4, 5] arr; // [1, 2]; --原数组被修改 arr = [1, 2, 3, 4, 5]; arr.splice(2, 2); // returns [3, 4] 参数:索引,想删除的元素个数 arr; // [1, 2, 5]; arr = [1, 2, 3, 4, 5]; arr.splice(1, 1, 'a', 'b'); //returns [2] 参数:第三个开始是要添加的值,再删除的位置开始添加、拼接 arr; // [1, "a", "b", 3, 4, 5]
arr.forEach( function( x , index){ ...} ); --数组遍历 函数为参数,x为值、index索引 IE 9+
var arr = [1, 2, 3, 4, 5];
arr.forEach(function(x, index, a){
console.log(x + '|' + index + '|' + (a === arr));
}); // 1|0|true // 2|1|true // 3|2|true // 4|3|true // 5|4|true
arr.map( function(x) { ...} ); ---数组映射,在数组的基础上做一些变动 函数为参数,x为值
var arr = [1, 2, 3];
arr.map(function(x) {
return x + 10; }); // [11, 12, 13] arr; // [1, 2, 3] --原数组没有被修改
arr.filter( function( x , index){ ...} ); --数组过滤、筛选 函数为参数,x为值、index索引
var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; arr.filter(function(x, index) { return index % 3 === 0 || x >= 8; }); // returns [1, 4, 7, 8, 9, 10] arr; // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] ---原数组没有被修改
arr.every/some( function(x) { ...} );
//数组判断,是否符合条件,every代表每一个值(x);some代表至少存在一个值满足条件
var arr = [1, 2, 3, 4, 5]; var arr = [1, 2, 3, 4, 5]; arr.every(function(x){ arr.some(function(x) { return x<10; return x === 3; }); //true }); // true arr.every(function(x){ arr.some(function(x) { return x<3; return x === 100; }); //false }); // false
arr.reduce/reduceRight( function(x) { ...} ); 数组中的值两两进行操作、判断
var arr = [1, 2, 3]; var sum = arr.reduce(function(x, y) { return x + y; //第一个参数为函数,第二个为第一个参数的x;若没有,则x是数组第一个数, }, 0); // 6 y为第二个数 arr; //[1, 2, 3] --原数组未被修改 arr = [3, 9, 6]; var max = arr.reduce(function(x, y) { console.log(x + "|" + y); return x > y ? x : y; }); // 3|9 9|6 9 max; // 9
max = arr.reduceRight(function(x, y) { //判断的顺序从后 往前 console.log(x + "|" + y); return x > y ? x : y; }); // 6|9 9|3 max: 9
arr.indexOf/lastIndexOf(3); //数组检索 ,last..从后往前找,返回的都是坐标(最后一位索引-1 )
var arr = [1, 2, 3, 2, 1]; arr.indexOf(2); // 1 --查找2 arr.indexOf(99); // -1 --没找到 arr.indexOf(1, 1); // 4 --查找1,从索引1(第二个数)开始查找 arr.indexOf(1, -3); // 4 arr.indexOf(2, -1); // -1 arr.lastIndexOf(2); // 3 arr.lastIndexOf(2, -2); // 3 arr.lastIndexOf(2, -3); // 1
Array.isArray([]); true ---判断是否为数组
[] instanceof Array; // true
({}).toString.apply([]) === '[object Array]'; // true
[].constructor === Array; // true
数组与字符串
var str = "hello world"; str.charAt(0); // "h" str[1]; // e --一般不用这样(数组方法操作字符串) Array.prototype.join.call(str, "_"); //利用数组方法操作字符串 // "h_e_l_l_o_ _w_o_r_l_d"
9、函数(对象)
function fun(){ ...}; //作用全局,声明会提前到最开始
var fun=function(){ ...}; //函数变量
(function(){ ...})(); //立即执行
return function(){ ...}; //作为返回值
var fun=function another(){ ...}; //命名式函数
var fun = new Function('a','b',' console.log(a+b); '); //fun(1,2); =3
var fun = Function('a','b',' console.log(a+b); '); //最后一个为函数体,前面都是参数
10、this 我也还不懂
this.document===document;
this===window
this.a=37;
window.a ; ---37
function fun(){ return this; } fun()===window; --严格模式下为undefined
var o={ f : function() { return this.a + this.b } }; var p= Object.create( o ); p.a=1; p.b=4; console.log( p.f() ); //5 --this 可以取到 p.a