在函数中不定义return就会调用默认的隐形return,就是return undifind!!!
字符串部分:
es6用反引号表示多行字符串,就是1左边那个案件。
用 `你好, ${name}, 你今年${age}岁了!`代替+号拼接的字符串 '你好, ' + name + ', 你今年' + age + '岁了!'
打点调用:
toUpperCase()把一个字符串全部变为大写
toLowerCase()把一个字符串全部变为小写
indexOf()会搜索指定字符串出现的位置
substring()返回指定索引区间的子串
数组部分:
slice()就是对应String的substring()版本,它截取Array的部分元素,然后返回一个新的Array
push()向Array的末尾添加若干元素,pop()则把Array的最后一个元素删除掉
如果要往Array的头部添加若干元素,使用unshift()方法,shift()方法则把Array的第一个元素删掉
sort()可以对当前Array进行排序,它会直接修改当前Array的元素位置,直接调用时,按照默认顺序排序
reverse()把整个Array的元素给掉个个,也就是反转
splice()方法是修改Array的“万能方法”,splice(a,b,c,d)从索引a开始删除b个元素然后添加c,d元素
concat()方法把当前的Array和另一个Array连接起来,并返回一个新的Array
join()方法是一个非常实用的方法,它把当前Array的每个元素都用指定的字符串连接起来,然后返回连接后的字符串
对象部分:
正则:
^ 以。。。开头
$ 以。。。结尾
\w 匹配字母或数字
\d 匹配数字
. 可以匹配任意字符
\s 匹配一个空格
*匹配任意个字符(包括0个)
+ 表示至少一个字符
? 表示0或1个字符
{n,m} 表示n到m个字符
[0-9a-zA-Z\_]可以匹配一个数字、字母或者下划线
^(\d{3})-(\d{3,8})$分别定义了两个组在RegExp对象上用exec()方法提取出子串
加个?就可以让\d+采用非贪婪匹配
当我们指定g标志后,每次运行exec(),正则表达式本身会更新lastIndex属性,表示上次匹配到的最后索引
指定i标志,表示忽略大小写,m标志,表示执行多行匹配。
JSON:
如果只想输出指定属性,就用数组:JSON.stringify(xiaoming, ['name', 'skills'], ' ');
解析json就JSON.parse()
面向对象:
把要给a对象的原型指向B,看上去a就像从b继承的,a就拥有自己的属性和B的方法。
关于原型:
arr ----> Array.prototype ----> Object.prototype ----> null
对于一个数组的原型链来说,数组的方法都定义在了array.prototype上,所以arr可以直接调用这些方法而不用声明
使用构造函数去新建对象:
function Student(name) {
this.name = name;
this.hello = function () {
alert('Hello, ' + this.name + '!');
}
}
然后直接var obj = new Student("..."),这样的话,每一个用此构造函数声明的对象都会具有hello这个函数。
function(){}():函数定义+()会自动执行一次;
关于遍历:
遍历中最常用的就是for循环;for(定义;判断;判断变量改变){执行条件};但是这个也是最不好用的遍历方法,应为这个方法效率较低,会占用大量运存;
一般来说对于对象,最好时用for。。。in来遍历,便利完了之后输出的是某键值对的值,格式是字符串。
for(var a in obj){alert (a)};这里的a是临时的一个变量,每次循环都会把对应的键值以string的格式保存在a中,a每次只保存一个string,循环结束后保留最后一个键值;如果只想找到对象自身的属性,而不是通过原型继承过来的就obj.hasOwnProperty(a);这个为true就是自己有的;如果用这个来遍历数组那得到的是a就是数组的每个索引值;
while和do while就是满足条件运行,不然就结束,不过dowhile是先执行一次在判断;
关于map和set结构(类型)
map是es6里新定义的一组键值对的结构:var m=new Map()/new Map([['6666',1],['jame',2]);如此从map中取键值对就很块:m.get('jame')得到的就是2;初始化一个map需要一个空或者一个二维数组;有以下方法:
var m = new Map(); // 空Map
m.set('Adam', 67); // 添加新的key-value
m.has('Adam'); // 是否存在key 'Adam': true
m.get('Adam'); // 67
m.delete('Adam'); // 删除key 'Adam'
m.get('Adam'); // undefined
因为一个键名只能对应一个键值,所以多次存储键值会覆盖;
对于set而言其实是跟map一样的,不过map不存储value,只是一组key的集合,由于key是不可重复的,所以set中没有重复的元素,初始化一个set需要空或者一个数组,重复元素会被自动剔除; s.add(4)通过add可以添加元素
对于map和set而言都不具备下标,即索引,所以是不能用for进行循环遍历的,为此es6引入了新的iterable类型,数组,mapset都是这个类型,是可以通过for of遍历
而for of的用法和for in是一样的,区别在于for in会遍历额外添加的属性,而for of只会遍历集合本身的属性
或者直接使用forEach()是es5引入的;用foreach接收一个函数,每一次遍历就会回掉该函数
例如
var a = ['A', 'B', 'C'];
var s = new Set(['A', 'B', 'C']);
var m = new Map([[1, 'x'], [2, 'y'], [3, 'z']]);
a.forEach(function (element, index, array) {
// element: 指向当前元素的值
// index: 指向当前索引
// array: 指向Array对象本身
alert(element);
});
s.forEach(function (element, sameElement, set) {
alert(element);
});
m.forEach(function (value, key, map) {
alert(value);
});
对于函数:对于函数而言有一个只在函数内部有用的关键字:arguments,永远指向当前函数的传入所有参数;rest参数是只能够写在最后的形参,写作...rest,实际的传参多于形参的部分会被填充成数组存在rest下。
变量作用域:
在函数内部定义,就只作用于内部,外部无法调用,如果定义在使用之后,会自动提升变量的声明,但是不会提升变量的赋值,全局定义的变量会绑定到window上,最好是定义一个全局变量,然后把所有的变量和函数定义到这个全局变量之中,就不会出现文件的冲突了。使用let在局部作用域中声明变量;用const来声明一个常量。
方法:
方法就是绑定到对象上的函数:
var xiaoming = {
name: '小明',
birth: 1990,
age: function () {
var y = new Date().getFullYear();
return y - this.birth;
}
};
xiaoming.age; // function xiaoming.age()
xiaoming.age(); // 今年调用是25,明年调用就变成26了
this是指向调用时的对象;最好在使用的时候现在函数内部定义var that = this;先用that捕获到this指向的函数,然后用that。调用,定义其他函数;
或者是使用apply()这是函数本身的方法:age.apply(a,b)意思是this指向A,传入参数为B。
可以用作计数:
var count = 0;
var oldParseInt = parseInt; // 保存原函数
window.parseInt = function () {
count += 1;
return oldParseInt.apply(null, arguments); // 调用原函数
};
// 测试:
parseInt('10');
parseInt('20');
parseInt('30');
count; // 3
关于一些方法:
map():
遍历数组;就是把一个函数作用在每一个元素上并生成一个新的数组
function pow(x) {
return x * x;
}
var arr = [1,2,3,4,5,6,7,8,9];
arr.map(pow); // [1, 4, 9, 16, 25, 36, 49, 64, 81]
reduce():
把一个函数轮流作用在每个元素上并返回一个值:
[x1, x2, x3, x4].reduce(f) = f(f(f(x1, x2), x3), x4)
filter():
和map()差不多,但是是依次作用于数组之后返回一个布尔值,根据布尔值决定是否保留该元素;true就保留,false就不保留;
var arr = [1, 2, 4, 5, 6, 9, 10, 15];
var r = arr.filter(function (x) {
return x % 2 !== 0;
});
r; // [1, 5, 9, 15]
在filter里接受的回掉函数可以有多个参数额,通常是某个元素,位置,数字本身,也就是(element,index,self)
所以去重的话;r = arr.filter(function (element, index, self) {
return self.indexOf(element) === index;
});
就可以了
sort();
对于sort,是一种快速地数组排序方法,arr.sort()但是排序的默认依据是ASCII码,如果需要使用自定的规则:
var arr = [10, 20, 1, 2];
arr.sort(function (x, y) {
if (x < y) {
return -1;
}
if (x > y) {
return 1;
}
return 0;
}); // [1, 2, 10, 20]
而且sort方法是直接对数组的修改,他返回的结果是当前的数组。
闭包:
不立即调用该函数,在后面按需调用:
function lazy_sum(arr) {
var sum = function () {
return arr.reduce(function (x, y) {
return x + y;
});
}
return sum;
}
在调用的时候返回的是求和函数
箭头函数
x=>x*x 相当于 function(x){return x*x}
如果有多个参数需要定义的时候就为
(x, y) => x * x + y * y
如果有多条执行语句的时候就
x => {
if (x > 0) {
return x * x;
}
else {
return - x * x;
}
}
如果需要返回一个对象的时候就外加()
x => ({ foo: x })
重点在于,箭头函数内部的this指向是词法作用域,即谁调用,就指向谁,所以使用箭头函数的时候就不用var _this=this;这种提前锁定this指向的写法
ES6
es6新引进了一种数据类型,就是generator;
定义如下:
function* foo(x) {
yield x + 1;
yield x + 2;
return x + 3;
}
在执行的时候,可以返回多个值,但是如果直接调用的话是不会返回所需要的值的,他只是创建了一个generator对象,并没有去执行,调用而言一种是不断的调用该对象的next()方法:next()方法可以带一个参数,该参数就会被当作上一个yield表达式的返回值
var a = foo(5)
a.next(); 返回的是{value:6,done:false;}
a.next(); 返回的是{value:7,done:false;}
a.next(); 返回的是{value:8,done:true;}
在返回的对象中,value代表的是运行一次之后的值,done代表的是这个generator是否完全执行完。
第二种调用方式就是:直接用for...of 调用,这样不用我们自己判断done的值;这种用法不会返回最后自己定义的return的返回值,只会执行yield的操作并返回值。
for (var x of foo(5)) {
console.log(x); // 依次输出6,7
}
浏览器对象
window 表示当前浏览器的窗口,这个对象有innerWidth和innerHeight属性,可以获取浏览器的可视区域的宽高,兼容至ie8。
还有outerWidth和outerHeight获取整个浏览器的窗口宽高。
navigator表示浏览器的信息,最常用的属性:appName浏览器名称,appVersion浏览器版本,language浏览器设置的语言,platform操作系统类型,userAgent浏览器设定的User-Agent字符串。
/Android|webOS|iPhone|iPod|BlackBerry/i.test(navigator.userAgent) ? true : false;判断是否是移动端
screen表示屏幕的信息,常用的属性:width屏幕宽度,height屏幕高度,colorDepth颜色位数
location表示当前页面的url信息。location.href可以获取到完整的url。
加载一个新页面就location.assign(),重新加载调用location.reload()
document表示当前页面,是整个dom树的根节点。document对象有个cookie属性,可以获取到到当前页面的cookie,因此服务器再设置cookie的时候必须使用httpOnly这个选项设定cookie不能被js所读取
history表存了浏览器的历史纪录,js可以调用history的back()和forward()功能就相当于是用户点击了浏览器的后退/前进按钮。由于ajax调用的话,最好是不要使用到history这个东西。
可以使用parentElement.insertBefore(newElement, referenceElement);,子节点会插入到referenceElement之前。
表单
md5 提交的时候:
要想不改变用户的输入,可以利用<input type="hidden">实现:
<!-- HTML --><form id="login-form" method="post" onsubmit="return checkForm()">
<input type="text" id="username" name="username">
<input type="password" id="input-password">
<input type="hidden" id="md5-password" name="password">
<button type="submit">Submit</button></form>
<script>function checkForm() {
var input_pwd = document.getElementById('input-password');
var md5_pwd = document.getElementById('md5-password');
// 把用户输入的明文变为MD5:
md5_pwd.value = toMD5(input_pwd.value);
// 继续下一步:
return true;
}
</script>
用return:true来确定继续提交,如果不符合规定就return false。
操作文件:
当一个表单包含<input type="file">时,表单的enctype必须指定为multipart/form-data,method必须指定为post,浏览器才能正确编码并以multipart/form-data格式发送表单的数据。
对于文件格式的处理,只能靠判断后缀名来处理:
varf = document.getElementById('test-file-upload');
var filename = f.value; // 'C:\fakepath\test.png'if (!filename || !(filename.endsWith('.jpg') || filename.endsWith('.png') || filename.endsWith('.gif'))) {
alert('Can only upload image file.');
return false;
}
h5的file api提供了file 和file reader,下面的代码演示读取用户选取图片并预览。
var
fileInput = document.getElementById('test-image-file'),
info = document.getElementById('test-file-info'),
preview = document.getElementById('test-image-preview');
// 监听change事件:
fileInput.addEventListener('change', function () {
// 清除背景图片:
preview.style.backgroundImage = '';
// 检查文件是否选择:
if (!fileInput.value) {
info.innerHTML = '没有选择文件';
return;
}
// 获取File引用:
var file = fileInput.files[0];
// 获取File信息:
info.innerHTML = '文件: ' + file.name + '<br>' +
'大小: ' + file.size + '<br>' +
'修改: ' + file.lastModifiedDate;
if (file.type !== 'image/jpeg' && file.type !== 'image/png' && file.type !== 'image/gif') {
alert('不是有效的图片文件!');
return;
}
// 读取文件:
var reader = new FileReader();
reader.onload = function(e) {
var
data = e.target.result; // 'data:image/jpeg;base64,/9j/4AAQSk...(base64编码)...'
preview.style.backgroundImage = 'url(' + data + ')';
};
// 以DataURL的形式读取文件:
reader.readAsDataURL(file);
});
ajax:
异步请求
function Ajax(type, url, data, success, failed){
// 创建ajax对象
var request = new XMLHttpRequest(); // 新建XMLHttpRequest对象
// 连接服务器open
if(type == 'GET'){
if(data){
xhr.open('GET', url + '?' + data, true);
} else {
xhr.open('GET', url + '?t=' + random, true);
}
// 发送请求
xhr.send();
} else if(type == 'POST'){
xhr.open('POST', url, true);
// 如果需要像 html 表单那样 POST 数据,请使用 setRequestHeader() 来添加 http 头。
xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xhr.send(data);
}
// 处理返回数据
request.onreadystatechange = function () { // 状态发生变化时,函数被回调
if (request.readyState === 4) { // 成功完成
// 判断响应结果:
if (request.status === 200) {
// 成功,通过responseText拿到响应的文本:
return success(request.responseText);
} else {
// 失败,根据响应码判断失败原因:
return fail(request.status);
}
} else {
// HTTP请求还在继续...
}
}
原生的看看就行了,用的不多;
判断数据类型:
console.log([].constructor == Array);
console.log({}.constructor == Object);
console.log("string".constructor == String);
console.log((123).constructor == Number);
console.log(true.constructor == Boolean);
或者使用instanceof
(a instanceof Array) //a是否Array的实例?true or false
(a.constructor == Array) // a实例所对应的构造函数是否为Array? true or false
以上只能判断当前页面内部定义的东西,如果跨页面调用怎会出错
function isArray(o) {
returnObject.prototype.toString.call(o) === ‘[object Array]‘;
}
所以判断数组最好是用这个Array.isArray(“。。。”)