数据类型
数字
字符串
布尔:false
和true
数组
对象
null——空值
undefined——未定义。仅仅在判断函数参数是否传递的情况下使用
字符串
用''
或者""
包括的叫字符串。
转义字符:"\"
toUpperCase()——转换为大写
toLowerCase()——转换为小写
indexOf()——搜索指定字符串出现的位置,如果没有找到返回-1
subString(start,end)——字符串截取,索引值不包含end
数组
获取数组长度直接arr.length
通过索引修改值arr[2]=0;
indexOf()——搜索指定元素所在位置
slice(起始索引,结束索引)——截取元素,返回新的数组,包含起始索引,但是不包含结束索引,类似数学中[start,end)
push()——向数组末尾添加新元素
unshift()——想数组头部添加新元素
pop()——删除数组末尾的元素
shift()——删除数组头部的元素
sort()——数组排序
reverse()——数组反向
concat()——数组合并,返回新数组
join()——数组转换为字符串
splice(start,num,newElement)——数组修改万能方法。
var arr = ['Microsoft', 'Apple', 'Yahoo', 'AOL', 'Excite', 'Oracle'];
//从索引2开始删除3个元素,然后再添加两个元素:
arr.splice(2, 3, 'Google', 'Facebook');
//删除的元素 ['Yahoo', 'AOL', 'Excite']
arr;
//['Microsoft', 'Apple', 'Google', 'Facebook', 'Oracle']
对象
对象我粗暴的理解就是键值对。
var person={
name:'小明',
age:18,
sex:'男',
'middle-school':'NO.1 middle school'
}
访问属性使用.
,例如person.name
或者person['name']
,属性命名含有特殊字符的必须使用后一种方式,即person['middle-school']
判断对象中某一个属性是否存在使用in
或者hasOwnProperty()
,前者判断的属性不一定是对象私有也可能是继承的,后者可以判断对象是否拥有该属性。
//in
'name' in person //true
'height' in person //false
//hasOwnProperty()
person.hasOwnProperty('name') //true
person.hasOwnProperty('height') //false
对象的属性都是字符串,属性值什么类型都有。
遍历对象属性和属性值
var per={
name:'zch',
age:18,
'height-h':178
}
var x=per.hasOwnProperty('name');
for(item in per){
console.log(per[item])
}
函数
函数定义
(1)函数声明
function abc(x){
if(x>0){
return x;
}else{
return -x;
}
}
//*函数内部执行到return时语句会停止
(2)函数表达式
var abs=function(x){
return x > 0 ? x : -x;
};
(1)和(2)在定义上完全等价,但是使用上要注意,函数声明方式可以先调用后定义,也就是函数提升,表达式定义则不行,另外方式(2)本质上是一个赋值语句,因此在末尾要加;
变量
如果一个变量在函数体内部申明,则该变量的作用域为整个函数体,在函数体外不可引用该变量
如果两个不同的函数各自申明了同一个变量,那么该变量只在各自的函数体内起作用。换句话说,不同函数内部的同名变量互相独立,互不影响
由于JavaScript的函数可以嵌套,此时,内部函数可以访问外部函数定义的变量,反过来则不行
JavaScript的函数在查找变量时从自身函数定义开始,从“内”向“外”查找。如果内部函数定义了与外部函数重名的变量,则内部函数的变量将“屏蔽”外部函数的变量
变量也可以提升,不过不能提升值
由于JavaScript的变量作用域实际上是函数内部,我们在for循环等语句块中是无法定义具有局部作用域的变量的,也就是说for循环中的i或者j在函数内部都可以访问到。
方法
在一个对象中绑定函数,称为这个对象的方法。
'use strict';
var xiaoming = {
name: '小明',
birth: 1990,
age: function () {
function getAgeFromBirth() {
var y = new Date().getFullYear();
return y - this.birth;
}
return getAgeFromBirth();
}
};
xiaoming.age();
//在一个方法内部,this是一个特殊变量,它始终指向当前对象,也就是xiaoming这个变量。所以,this.birth可以拿到xiaoming的birth属性。
//针对函数内再套函数的问题,因为this指向发生了变化,可以使用that首先捕获this,在进行传值
高阶函数
高阶函数就是函数的参数是一个函数
function add(x, y, f) {
return f(x) + f(y);
}
add(-5,9,Math.abs)// Math.abs(-5) + Math.abs(6)==>5+6=11
高阶函数——map()
//jquery map() 返回一个jquery对象
//js原生map()返回一个数组
<input type="text">
<input type="text">
<input type="text">
var x=$("input").map(function(){
return $(this).val();
})
//返回{ 0: "气球", 1: "是否", 2: "水电费刹车发生"}
console.log(x)//返回objct
//get()是jq DOM操作方法,目标对象是获取的DOM元素,返回数组。
//结果[ "气球", "是否", "水电费刹车发生" ]
console.log(x.get())
在实际使用的时候,我们可以利用map方法方便获得对象数组中的特定属性值们,如下:
var users = [
{name: "张含韵", "email": "zhang@email.com"},
{name: "江一燕", "email": "jiang@email.com"},
{name: "李小璐", "email": "li@email.com"}
];
var emails = users.map(function (user) { return user.email; });
console.log(emails.join(", ")); // zhang@email.com, jiang@email.com, li@email.com
由map方法引发的一个js题目:
["1", "2", "3"].map(parseInt);
// 你可能觉的会是[1, 2, 3]
// 但实际的结果是 [1, NaN, NaN]
// 通常使用parseInt时,只需要传递一个参数.但实际上,parseInt可以有两个参数.第二个参数是进制数.可以通过语句"alert(parseInt.length)===2"来验证.
// map方法在调用callback函数时,会给它传递三个参数:当前正在遍历的元素, 元素索引, 原数组本身.
// 第三个参数parseInt会忽视, 但第二个参数不会,也就是说,parseInt把传过来的索引值当成进制数来使用.从而返回了NaN.
//应该使用如下的用户函数returnInt
function returnInt(element){
return parseInt(element,10);
}
["1", "2", "3"].map(returnInt);// 返回[1,2,3]
parseInt()方法
语法:parseInt(string, radix)
string 必需。要被解析的字符串。
radix 可选。
表示要解析的数字的基数。该值介于 2 ~ 36 之间。
如果省略该参数或其值为 0,则数字将以 10 为基础来解析。如果它以 "0x" 或 "0X" 开头,将以 16 为基数。
如果该参数小于 2 或者大于 36,则 parseInt() 将返回 NaN。
所以:["1", "2", "3"].map(parseInt)相当于
[parseInt("1", 0), parseInt("2", 1), parseInt("3", 2)]
parseInt("3", 2) 的第二个参数是界于 2-36 之间的,之所以返回 NaN 是因为 字符串 "3" 里面没有合法的二进制数,所以 NaN
高阶函数——reduce
Array的reduce()把一个函数作用在这个Array的[x1, x2, x3...]上,这个函数必须接收两个参数,reduce()把结果继续和序列的下一个元素做累积计算,其效果就是:
[x1, x2, x3, x4].reduce(f) = f(f(f(x1, x2), x3), x4)
比方说对一个Array求和,就可以用reduce实现:
var arr = [1, 3, 5, 7, 9];
arr.reduce(function (x, y) {
return x + y;
}); // 25
高阶函数——filter()
过滤器,返回true
保留,false
丢弃,类似map()
,接收一个函数。
//筛选出字符串
var arr=[1,2,4,'dfdf',343,'asdfsad'];
var x=arr.filter(function(x){
return typeof(x)=='string'
})
console.log(x)
filter回调函数可以带三个参数
var arr = ['A', 'B', 'C'];
var r = arr.filter(function (element, index, self) {
console.log(element); // 依次打印'A', 'B', 'C'
console.log(index); // 依次打印0, 1, 2
console.log(self); // self就是变量arr
return true;
});
高阶函数——sort()
sort()排序时先把元素转换为字符串再进行判断,因此数字排序有时候不正确,因此需要我们自己传入一个比较函数。
arr.sort(function(x,y){
if(x<y){
return -1;
}
if(x>y){
rerturn 1;
}
return 0;
})
//当然最简洁是这样写
arr.sort(function(x,y){
return x-y;//正序
return y-x;//倒序
})
sort()方法会对当前array进行修改,返回时当前的arry;
闭包
箭头函数
(x,y)=> x*y
等同于
function(x,y){
return x*y;
}
generator
ES6标准,generator由function定义(注意多出的号),并且,除了return语句,还可以用yield返回多次
标准对象
在js中一切都是对象。
包装对象
在js中只有对象才可以使用.
加属性进行访问,js的三个基本类型number
,string
和boolean
看着人家有对象心里不平衡,自己也想有对象,于是就借助包装对象来让自己变成对象,有两个方式,一个是隐式转换一个是显式转换。
什么是隐式转换呢?看下面例子:
var str='asfkjas';
console.log(str.length);
变量str是一个字符串,但是却可以使用.
加属性的形式获取到字符长度,这大大超出了我们的预知,完全是反人类啊,其实浏览器默默的给他包装成了一个对象,本质上是这样的:
var str='asfkjas';
console.log(new String(str).length);
再例如:
var str='hello';
str.a='haha';
console.log(str.a)
结果是undefined
,第二行声明的时候默认是new String(str).a='haha'
,用完就立即舍弃了,所以打印的时候并没有赋值,结果是undefined
;
具体解释点击这里
建议包装对象不要随意使用,涉及到类型转换的时候建议使用以下方式:
不要使用new Number()、new Boolean()、new String()创建包装对象;
用parseInt()或parseFloat()来转换任意类型到number;
用String()来转换任意类型到string,或者直接调用某个对象的toString()方法;
通常不必把任意类型转换为boolean再判断,因为可以直接写if (myVar) {...};
typeof操作符可以判断出number、boolean、string、function和undefined;
判断Array要使用Array.isArray(arr);
判断null请使用myVar === null;
判断某个全局变量是否存在用typeof window.myVar === 'undefined';
函数内部判断某个变量是否存在用typeof myVar === 'undefined'。
null
和undefined
没有toString()方法。
number调用toString()时应该这样:
123..toString(); // '123', 注意是两个点!
(123).toString(); // '123'
为什么?不要问为什么?这就是js的乐趣!
String()和toString()方法的区别
两个转换小技巧:
var x1=x+'';
console.log(typeof(x1));//string
var y='123';
var y1=y-0;
console.log(typeof(y1));//number
date
var now = new Date();
now; // Wed Jun 24 2015 19:49:22 GMT+0800 (CST)
now.getFullYear(); // 2015, 年份
now.getMonth(); // 5, 月份,注意月份范围是0~11,5表示六月
now.getDate(); // 24, 表示24号
now.getDay(); // 3, 表示星期三
now.getHours(); // 19, 24小时制
now.getMinutes(); // 49, 分钟
now.getSeconds(); // 22, 秒
now.getMilliseconds(); // 875, 毫秒数
now.getTime(); // 1435146562875, 以number形式表示的时间戳
new Date(1487644350463)//获取一个时间戳之后使用Date()转换成时间格式
RegExp
基础规则
用\d可以匹配一个数字
\w可以匹配一个字母或数字
.
可以匹配任意字符用
*
表示任意个字符(包括0个)用
+
表示至少一个字符用
?
表示0个或1个字符用
{n}
表示n个字符用
{n,m}
表示n-m个字符
JSON
JSON还定死了字符集必须是UTF-8,表示多语言就没有问题了。为了统一解析,JSON的字符串规定必须用双引号"",Object的键也必须用双引号""。
面向对象编程
js没有类的概念,可是通过__prototype__
来实现继承,但是这个方法不要使用,有兼容问题,可以通过创建函数的形式来实现类似java类继承。
// 原型对象:
var Student = {
name: 'Robot',
height: 1.2,
run: function () {
console.log(this.name + ' is running...');
}
};
function createStudent(name) {
// 基于Student原型创建一个新对象:
var s = Object.create(Student);
// 初始化新对象:
s.name = name;
return s;
}
var xiaoming = createStudent('小明');
xiaoming.run(); // 小明 is running...
xiaoming.__proto__ === Student; // true