script标签
1、async: 异步下载当前脚本,不阻塞后续代码的执行
2、charset: 字符集
3、defer: 表示当前脚本延迟到文档完全被解析和显示后在执行 defer="defer"
4、src: 文件路径
5、language: 语言
6、type: 脚本类型
'use strict' 严格模式
作用域和作用域链
作用域: 变量的有效范围,函数从内往外搜索变量,如果内部没有变量就去外部搜索直接全局对象
作用域链: 决定哪些变量能够被当前函数访问及访问顺序
函数对象有一个[[Scope]]属性,包含了函数被创建作用域中对象的集合,集合被称为函数的作用域链scope chain,它决定了哪些数据能被函数访问
function doSomething(){
var blogName="Jessica";
function innerSay(){
alert(blogName);
}
innerSay();
}
alert(blogName); //脚本错误
innerSay(); //脚本错误
变量生命周期:全局的变量是永久的,函数内的局部变量当退出函数时,局部变量即消毁,
预解析
JS执行时先将代码中所有 var定义变量和function(){} 进行提取,函数内部变量除外。
将var的变量赋为undefined
将函数都为函数本身function getName(){},所以在调用函数时无论在前还是在后都会被调用。
Example:
var add = 'bbb';
function add(){console.log('aaa')}
add(); 报错
闭包
闭包: 函数嵌套,内部函数调用外部函数的局部变量,内部函数执行完后自动消毁,外部函数的变量不会被回收一直保存在内存中.
<script>
var fun = function(){
var a = 1;
return function(){
a++;
alert(a);
}
}
var f = fun(); // 这里返回了匿名函数的引用,里面的局部变量就不会被消毁
f(); // 2
f(); // 3
f(); // 4
</script>
数据类型
JS的七种数据类型: Number、String、Boolean、Undefined、Object、Function、Symbol
一、 获取数据类型
获取数据的类型: 返回的值(number、string、boolean、array、object、function、undefined、symbol)
Object.prototype.toString.call(val) - 获取JS私有的 Class 属性, 这个隐藏的属性是不能被改的
// 判断类型
function returnType(val) {
let typeName;
if (typeof val === 'object') {
let typeName = Object.prototype.toString.call(val);
if (typeName == '[object Array]') {
return 'array'
}
else if (typeName == '[object Object]') {
return 'object'
}
else if(typeName == '[object Null]'){
return 'null'
}
}
else {
return typeof val;
}
}
二、NaN 非数值
isNaN() 是否是一个NaN非数值, 如果是数字返回false, 否则返回true
isNaN(NaN); // true
isNaN(10); // false
isNaN('10'); // false 转换后是一个数字
isNaN('blue'); // true 转换后不会是一个数字
isNaN(true); // false true转换后为1是一个数字
三、类型转换
String to Number: 类型转换只支持十进制(30)、二进制(0b111)、八进制(0o13)、十六进制(0xFF)
Number比parseInt和parseFloat更好的选择,一些古老的浏览器parseInt还支持0开头数字的八进制前缀,这是错误的,在任何环境下都建议传入parseInt第二个参数
1、Number() 布尔转换成1或0,null返回0,undefined返回NaN
2、parseiInt(num, 10): 第二个参数来规则用哪个进制来转换
3、parseFloat(): 直接将字符串以十进制来转换
包装类
var str = '1234567';
str.length; // 返回7
str原始值只是一个字符串,为什么会有属性和方法,它经历了一个过程叫『包装类』
JS在执行些方法的时候会隐式的转成 new String(str),执行完后在乐逍毁掉
函数
一、函数没有重载: 当两个函数名相同,后面的函数会覆盖掉之前的函数
function getUserName(){
console.log('a');
}
function getUserName(){
console.log('b');
}
getUserName(); // 'b'
二、声明函数和匿名函数
function person() { ... }; // 声明
var person = function() { ... } // 匿名
Example:
getName(); // b
var getName = function(){ // 优先级要高于声明函数,但要必须执行到这里才有效
console.log('a');
};
getName(); // a
function getName(){
console.log('b');
}
getName(); // a
三、函数参数
1、形参、实参
function add(a, b){ return a+b } // 形参
add(1,2) // 实参
2、arguments数组: 函数参数的数组
3、callee 函数的调用当前函数的本身,可以使用arguments.caller(), 可以用于递归
function factorial(num){
if(num < 1){
return 1;
}
else{
return num * arguments.callee(num-1);
}
}
4、caller 返回被调用函数的本身
function outer() {
inner();
}
function inner() {
alert(arguments.callee); // function inner(){ ... }
alert(arguments.callee.caller); // function outer(){ ... }
}
outer();
四、如果函数没有return返回undefined
var fn = function(){ };
fn(); // undefined
call()、apply()、bind()
Function.prototype.call() 和 Function.prototype.apply() 用于改变函数的this指向
一、call无参
var obj1 = {
name: 'siguang',
getName: function(){
return this.name;
}
}
var obj2 = {
name: 'lulu'
}
console.log(obj1.getName()); // siguang
// 注意这里是将getName中的this指定指向了obj2,并且执行了getName()函数
var n1 = obj1.getName.call(obj2);
console.log(n1); // lulu
二、apply有参
var objA = {
num: 10,
add: function(a, b){
return a + b + this.num;
}
}
var objB = {
num: 20
}
var n1 = objA.add(1, 2);
console.log(n1); // 13
var n2 = objA.add.call(objB, 1, 2); // 如果objA.add.apply(objB, [1,2]);
console.log(n2) // 23
三、bind(): 一个函数绑定之后,可以保持传递this的上下文
bind与call、apply的用法不同,但作用是一样的.
var obj = {
nameStr: 20,
getName: function(){
setTimeout(function(){
console.log(this.nameStr);
}.bind(obj), 10)
}
}
// 输出20,如果不加bind(),this指向window所以输出的是undeined
obj.getName();
void(0)
这个操作符允许插入一个计算结果等效于undefined的表达式。
void操作符经常仅仅是用来获得undefined值,比如经常使用到的“void(0)”(这等效于“void 0”)
当浏览器遇到一个javascript:URI,它会运算带有URI的代码,然后将计算结果替换当前页面的内容,除非它的返回值是undefined。void操作符可以被用于返回undefined
<a href="javascript:void(0);">Click here to do nothing</a>
装箱、拆箱转换
一、装箱: 把基本类型转换为对应的对象
var symbolObject = Object(Symbol("a"));
console.log(typeof symbolObject); // object
console.log(symbolObject instanceof Symbol); // true 是Symbol的实例
console.log(symbolObject.constructor == Symbol); // true
二、拆箱
对象到String和Number转换同都遵循『先拆箱在转换』的规则,通过拆箱把对象变成基本类型,在从基本类型转为string或number
toString(): 将该对象的原型始以字符串形式返回 xx.toString(); // 'xx'
valueOf(): 返回最适合该对象的类型的原始值
表达式
var testA = 3 && 2; // 返回 2,如果左侧为真返回右侧,否则返回左侧
var testB = 0 || 3; // 返回3,如果左侧为假返回右侧
var a = 1; console.log(!!a); // 返回true,!!强制转换成布尔值
var a = '123.563'; console.log( +a ); // 123.563,+转换成数值类型
语句
for(var i=0; i<10; i++){}
do{....} while(express)
while(){ ... }
for( in ){}
break 退出整个循环 continue 跳出当前循环,继续执行下一个循环
switch case default
定时器的运行机制
JavaScript是通过事件循环(event loop)来实现的,事件循环机制也就是今天要说的JavaScript运行机制。
第一,判断JS是同步还是异步,同步进入主线程,异步则进入event table。
第二,异步任务在event table中注册函数,当满足触发条件后,被推入event queue(事件队列)。
第三,同步任务进入主线程后一直执行,直到主线程空闲,才会去event queue中查看是否有可执行的异步任务,如果有就推入主线程
异步为了避免一些长时间任务造成的无意义等待,和假死状态 - ajax、定时器、Promise
Example:
// HTML5规范规定最小时间不能小于4ms(毫秒),如果小于4会被当4来处理,Chrome可以设置1ms
console.log(1);
setTimeout(function(){
console.log(2);
}, 0);
console.log(3); // 1、3、2
JS异步有哪些方式
1、setTimeOut()
2、Promise
3、Generator
4、async、await
5、ajax
宏任务和微任务
JS的运行机制。也就是事件循环。解释一下:
第一,执行一个宏任务(主线程的同步script代码),过程中如果遇到微任务,就将其放到微任务的事件队列里。
第二,当前宏任务执行完成后,会查微任务的事件队列,将全部的微任务依次执行完,再去依次执行宏任务事件队列。
宏任务:包括整体script代码,setTimeout,setInterval
微任务:Promise,process.nextTick。
setTimeout(() => {
console.log(1)
}, 3000);
new Promise((resolve, reject) => {
console.log(2);
resolve('2')
})
.then(function(){
console.log(3)
});
console.log(4); // output 2、4、3、1
事件
一、事件机制: 事件捕获 和 事件冒泡, IE11之前没有捕获
二、事件委托
事件委托(也称事件代理): 将事件绑定到父元素上,利用冒泡机制来对点击的元素进行处理
<div id="boxList">
<ul>
<li data-attr="a1">aaa</li>
<li data-attr="a2">bbb</li>
<li data-attr="a3">ccc</li>
</ul>
</div>
<script type="text/javascript">
var oList = document.querySelector('#boxList');
oList.onclick = function(e){
var arrtName = e.target.getAttribute('data-attr');
console.log(arrtName);
}
</script>
三、自定义事件
四、onLoad与DOMContentLoaded事件的区别
onLoad: 是当所有资源都加载完成后在执行onLoad函数内的程序
DOMContentLoaded: 是当DOM树加载完成后就执行此函数内的程序
五、onmouseover、onmouseout与onmouseEnter、onmouseLeave
onmouseover、onmouseout 会冒泡
onmouseEnter、onmouseLeave 不会冒泡
六、addEventListener(事件类型, 执行函数, boolear): 第三个参数,如果是true表示在捕获取中调用事件,false冒泡时调用
这里执行的函数不会被重载
var oSendBtn = document.querySelector('#sendBtn'); // 点击会输出'aa', 'bb'
oSendBtn.addEventListener('click', function(){
console.log('aa');
}, false);
oSendBtn.addEventListener('click', function(){
console.log('bb');
}, false);
概念
一、加载非阻塞脚本:
浏览器遇到 <script> 标签时,页面加载都会停下来,先执行js代码,然后在继续加载(因为不知道脚本里有没有document.wirte()
来向页面写内容,所以会需要先执行完js文件在继续)
使用动态创建DOM元素,将脚本加载放到</body>之前来加载,这样不会影响页面的内容展示
二、按需加载: 可以分图片按需加载,js文件按需加载、数据接需加载
图片按需加载使用的lazyload
JS按需加载类似模块化开发,只对依赖的文件进行加载
三、图片预加载: 通过new Images()来创建图像对象提前将图片进行加载
function preloadImg(url) {
var img = new Image();
img.src = url;
if(img.complete) {
//接下来可以使用图片了
//do something here
}
else {
img.onload = function() {
//接下来可以使用图片了
//do something here
};
}
}
跨域的解决方法
由于同源策略,安全性,ajax不同域下的数据不可以调用
跨域的产生: 1、同域名不同端口 2、同域名不同协议 3、主域和子域之间 4、子域和子域之间
解决跨域的方法:
一、JSONP
JSONP利用script标签中的src属性,src属性没有跨域限制,通过url的参数将回调函数的名称和数据请求给服务器,服务器接收到url参数进行处理,并将数据挂载到回调函数的参数并执行回调函数,客户端有与回调函数名相同,来处理这些数据
// 处理回调函数数据的函数
function doSomething(data) {
// 对data处理
}
var script = document.createElement("script");
script.src = "http://www.b.com/b.html?callback=doSomething";
document.body.appendChild(script);
二、document.domain:
适用于主域相同子域不同,比如 www.renrendai.com 和 action.renrendai.com
例如: 两个域下各有a.html和b.html, a通过iframe嵌到另一个子域b.html是无权访问b.html文档内的元素, 所以通过document.domain来设置
a.html:
document.domain = "www.we.com";
var iframe = document.createElement("iframe");
iframe.src = "http://a.we.com/b.html";
document.body.appendChild(iframe);
iframe.onload = function() {
console.log(iframe.contentWindow....); // 在这里操作b.html里的元素数据
}
b.html:
document.domain = "www.we.com"; // b页面必须要设置a.html
三、HTML5 postMessage() 处理iframe跨域问题
如果在一个主域中的a.html嵌套个 <iframe src="http://www.b.com/b.html" frameborder="0"></iframe>
postMessage有两个接口: postMessage(send) 发送数据和 onmessage接收数据事件通过e.data来获取到
Example:
// a.html
<iframe src="http://www.b.com/b.html" frameborder="0" id="messageId"></iframe>
var oMessage = document.getElementById('messageId');
window.onload = function(){
window.addEventListener('message', function(e){
console.log(e.data); // 接收b的数据
}, false);
oMessage.postMessage('发送给b的数据', 'http://www.b.com/b.html');
}
// b.html
window.onload = function(){
window.addEventListener('message', function(e){
console.log(e.data); // 接收a的数据
})
window.parent.postMessage('发送给a的数据', 'http://www.a.html/a.html');
}
传统的iframe跨域使用方法: http://www.cnblogs.com/snandy/p/3900016.html
四、window.name + iframe
window.name原理是利用同一个窗口在不同页面共用一个window.name,这个需要在a.com下建立一个代理文件c.html,使同源后a.html能获取c.html的window.name.
// a.html
var iframe = document.createElement("iframe");
iframe.src = "http://www.b.com/b.html";
document.body.appendChild(iframe); // 现在a.html里建一个引用b.html的iframe,获得b的数据
var flag = true;
iframe.onload = function() {
if (flag) {
iframe.src = "c.html"; // 这里在去加载c.html
// 判断是第一次载入的话,设置代理c.html使和a.html在同目录同源,这样才能在下面的else取到data
flag = false;
}
else {
// 第二次载入由于a和c同源,a可以直接获取c的window.name
alert(iframe.contentWindow.name);
iframe.contentWindow.close();
document.body.removeChild(iframe);
iframe.src = '';
iframe = null;
}
}
// b.html
window.name = "这是 b 页面的数据";
五、window.location.hash + iframe
b.html将数据以hash值的方式附加到c.html的url上,在c.html页面通过loaction.hash获取数据后传到a.html
// a.html
var iframe = document.createElement("iframe");
iframe.src = "http://www.b.com/b.html";
document.body.appendChild(iframe); // 在a页面引用b
function check() {
// 设置个定时器不断监控hash的变化,hash一变说明数据传过来了
var hashs = window.location.hash;
if (hashs) {
clearInterval(time);
alert(hashs.substring(1));
}
}
var time = setInterval(check, 30);
//b.html
window.onload = function() {
var data = "this is b's data";
var iframe = document.createElement("iframe");
iframe.src = "http://www.a.com/c.html#" + data;
document.body.appendChild(iframe); // 将数据附加在c.html的hash上
}
//c.html
// 获取自身的hash再传到a.html的hash里,数据传输完毕
parent.parent.location.hash = self.location.hash.substring(1);
六、CORS跨域资源共享
1、CORS概念: 是指跨域资源共享, 用于解决前端跨域问题, 使用自定义头部让浏览器与服务器进行沟通, 来进行请求成功或失败
原理: 服务器对header设置一个Access-Control-Allow-Origin: *, 开启跨域请求。
*表示接受所有域名的请求。也可以指定特定的域名 Access-Control-Allow-Origin: http://www.client.com。
2、CORS优点: 跨域最常用的是JSONP但这种方式是通过Get的方式请求src完成的,很多跨域问题JSONP无法解决,比如:
1)post请求跨域
2)"script error" 的脚本错误提示
3)canvas中无法获取跨域图片的信息,如果使用CORS上面几个问题就可以解决
3、CORS缺点:
1)cookie不会随请求发送,也不会响应
2)不能设置请求头的Content-Type字段
3)不能访问响应头信息
面向对象
面向对象的特点: 封装、继承、多态
对象组件: 私有、公有属性、方法和特权方法
一、对象的数据属性和访问器属性(getter、setter)
var o = { a: 1 };
o.b = 2;
console.log(o.a, o.b); //1 2
二、constructor属性: 指向这个原型的构造函数,如果是类式继承需要修改子类的constructor的指向,如果不改子类会指向父类.
三、原型和原型链:
prototype原型: 在创建函数的时候JS会为这个函数自动加上prototype属性
原型链: 每一个构造函数都有一个prototype, prototype包含一个指向构造函数的指针, 而实例包含指向原型的对象的指针, 都是通过 __proto__ 属性来指向
1、构造函数实例化后,prototype下的所有属性和方法都为公用的一套, 这样为了节省资源提高性能
2、优先级: 如果同时在构造函数内或prototype中定义相同的属性或方法名, 会先找到执行构造函数内的属性或方法, 如果没有在到prototype中查找。
__proto__属性: __proto__是实例与prototype之间的链接,实例的__proto__指向构造函数的prototype.function F(){};
var f = new F();
console.log(f.__proto__ === F.prototype); // true
Object.prototype是顶级对象,所有对象都继承它
四、继承
每个对象都是由Object.prototype对象继承的
继承分为: 类式继承、原型链继承、拷贝继承。
1、类式继承:
function Parent(){}
Parent.prototype.say = function(){
console.log('haha')
}
function Childer(){}
/* 将第一个类的实例赋给第二个类的原形,类式继承的原因
* 类的原型对象作用就是为类的原型添加公有方法,但不能直接访问这些属性和方法,必须通过原型prototype来访问
*/
Childer.prototype = new Parent();
// 上一步执行后prototype的constructor会指向Parent,所以需要修正回来
Childer.prototype.constructor = Childer;
Childer.prototype.getAuthor = function(){ console.log('siguang') }
2、原型链继承:
// 原型链式继承
/*
* 流程:
* 1、clonePlan调用blood属性会在clonePlan查找所有属性,
* 2、如果没有找到在看clonePlan的__proto__指象哪里,这里指向了F,到F对象下的prototype下查找
* 3、plane将prototype赋给了F的prototype所以最终找到了blood属性
*/
function extend(obj){
var F = function(){};
F.prototype = obj;
return new F();
}
// 定义一个类
var Plane = function(){
this.blood = 100;
this.attackLevel = 1;
this.defenseLevel = 1;
}
Plane.prototype = {
getBlood: function(){
console.log(this.blood);
},
getAttackLevel: function(){
console.log(this.attackLevel)
}
}
var plane = new Plane();
// 将类通过extend函数继承过来
var clonePlan = extend(plane);
clonePlan.blood = 1234;
clonePlan.attackLevel = 4567;
clonePlan.getBlood(); // 1234
clonePlan.getAttackLevel(); // 4567
3、拷贝继承
function extend(parent, childer){
for(var key in parent){
childer[key] = parent[key];
}
}
extend(a.prototype, b.prototype);
4、Object.create()继承
function Car(desc){
this.desc = desc;
this.color = 'red'
}
Car.prototype = {
getInfo: function(){
return `color: ${this.color}, desc: ${this.desc}`
}
}
// 注意这里的name : {value: 'lulu'} 必须是对象,必须是value在根一个值,要不报错
var child = Object.create(Car.prototype);
child.desc = 'aaa';
child.color = 'bbb';
// 改变子类不会影响到父类
console.log(child);
var childCar = child.getInfo();
console.log(childCar) // color: bbb, desc: aaa
var oCar = new Car('ccc');
console.log(oCar.getInfo()); /// color: red, desc: ccc
五、SuperClass.prototype = {} 与 SuperClass.prototype.getName = function(){} 区别
一个是将对象覆盖prototype, 一个是将方法添加到prototype中
存在的问题,SuperClass.prototype = {}这种方式,实例的对象没有constructor,
Ajax
一、XMLHttpRequrest 缓存
缓存只有在get请求中存在,如果服务端设置了缓存,如果在缓存失效前请求就会取到缓存的数据,解决有两种方法:
1、加If-Modified-Since头
xhr.setRequestHeader('If-Modified-Since', '0');
jquery中设置 $.ajax({ cache: false })
2、给请求的URL后加参数
let sendUrl = "http://host/getUser"+"?"+Math.random();
// 创建一个XMLHttpRequest对象
var xhr = window.XMLHttpRequrest ? new XMLHttpRequrest() : new ActiveXObject("Microsoft.XMLHTTP");
属性: 服务器响应
1、reponseText: 字符串响应数据
2、responseXML: 获取XML响应数据
3、timout: 设置超时请求时间
4、responseType: 设置返回数据类型
1、text: 字符串 2、document: Document对象 3、json: json数据 4、blob: 二进制对象 5、arrayBuffer: 二进制
方法:
1、open(请求类型,请求地址,同步/异步): 请求类型
2、send(): 请求发送到服务器
3、setRequestHeader(key,value): 设置请求头
4、getResponseHeader(header)、getAllResponseHeaders(): 获取响应头
事件:
1、onabort: 停止传输
2、onerror: 错误
3、onload:
4、ontimout: 超时执行的事件
5、onreadystatechange: 请求发送到服务器时,接收一些响应
readyState: XMLHttpRequest的状态,
0: 请求未初始化 1、服务器连接已建立 2、请求已接收 3、请求处理中 4、请求已完成,已响应
status: 200: 成功 404: 未找到资源
xhr.onreadystatechange = function(e){
if(this.readyState == 4 && this.state == 200){
console.log(this.reponseText)
}
}
6、upload: 上传 XMLHttpRequestUpload
function uploadFile() {
// 创建FormData对象
var fd = new FormData();
// 添加值
fd.append("fileToUpload", document.getElementById('fileToUpload').files[0]);
// 创建XMLHttpRequest()请求
var xhr = new XMLHttpRequest();
// 文件上传时侦听progress事件
xhr.upload.addEventListener("progress", uploadProgress, false);
xhr.addEventListener("load", uploadComplete, false); // 载入
xhr.addEventListener("error", uploadFailed, false); // 错误
xhr.addEventListener("abort", uploadCanceled, false); // 终止
// 请求方式和地址
xhr.open("POST", "test2.php");
// 发送请求到服务器
xhr.send(fd);
}
function uploadProgress(evt) {
// evt.loaded 当前上传的大小, evt.total 文件总大小
if (evt.lengthComputable) {
var percentComplete = Math.round(evt.loaded * 100 / evt.total);
document.getElementById('progressNumber').innerHTML = percentComplete.toString() + '%';
}
else {
document.getElementById('progressNumber').innerHTML = 'unable to compute';
}
}
function uploadComplete(evt) {
/* This event is raised when the server send back a response */
alert(evt.target.responseText);
}
function uploadFailed(evt) {
alert("There was an error attempting to upload the file.");
}
function uploadCanceled(evt) {
alert("The upload has been canceled by the user or the browser dropped the connection.");
}
content-type四种类型
get请求包括请求头、状态行
post请求包括请求头、状态行、请求主体(主体类型设置就是content-type来处理)
Content-Type:
一、application/x-www-form-urlencoded: 浏览器的原生 form 表单,如果不设置 enctype 属性,那么最终就会以 application/x-www-form-urlencoded 方式提交数据
jquery和ajax的默认的方式 content-type:「application/x-www-form-urlencoded;charset=utf-8」
header:
POST http://wwwexamplecom HTTP/11
Content-Type: application/x-www-form-urlencoded;charset=utf-8
** Form Data
incomeTime: "16:25:13"
serialNumber: "223"
incomeBank: "中央银行"
incomeAccount: "穷逼"
二、multipart/form-data: 一般用来上传文件,必须让 form 的 enctyped 等于这个值
content-type: multipart/form-data
POST http://wwwexamplecom HTTP/11
Content-Type:multipart/form-data; boundary=----WebKitFormBoundaryrGKCBY7qhFd3TrwA
** Request Payload
------WebKitFormBoundaryrGKCBY7qhFd3TrwA
Content-Disposition: form-data; name="text"
title
------WebKitFormBoundaryrGKCBY7qhFd3TrwA
Content-Disposition: form-data; name="file"; filename="chromepng"
Content-Type: image/png
PNG content of chromepng
------WebKitFormBoundaryrGKCBY7qhFd3TrwA--
三、application/json: 告诉服务端消息主体是序列化后的 JSON 字符串
POST http://wwwexamplecom HTTP/11
Content-Type: application/json;charset=utf-8
// ajax请求
var data = {'title':'test', 'sub' : [1,2,3]};
$ajaxpost(url, data)success(function(result){
});
// 发送
POST http://wwwexamplecom HTTP/11
Content-Type: application/json;charset=utf-8
** Request Payload
{"title":"test","sub":[1,2,3]}
四、text/xml: XML文件作为编码方式的需要用到的类型
POST http://wwwexamplecom HTTP/11
Content-Type: text/xml
** Request Payload
五、HTML5中的fromData异步上传表单
这里注意需设置 content-type:false 和 processData: false
function upThumbSubmit() {
if(!windowFormData) {
alert('your brower is too old');
return false;
}
var formData = new FormData($( "#upForm" )[0]);
var upLoadFile = documentquerySelector('upfile')files[0];
formDataappend('file': upLoadFile);
$ajax({
url:'?c=api&a=upload',
type:'post',
data:formData,
processData: false, // 不会被序列化
contentType: false,
dataType:'json',
success:function(data){
alert(data);
return false;
}
});
}
iframe父子页面的通信
Example:
parent.html:
<body>
<iframe src="child.html" frameborder="0" id="child"></iframe>
</body>
childe.html:
<body>
<div id="box"></div>
</body>
一、父页面获取子页面
<script>
var myIframe = document.querySelector('#child'),
childDocument;
if(myIframe.document){
childDocument = myIframe.docuemnt;
}
else{
childDocument = myIframe.contentWindow.docuemnt;
}
childDocument.querySelector('#box').innerHTML = 'xxxx';
</script>
1、先获取iframe节点
var myIframe = document.querySelector('#child'); // 或 myIframe = window.frames['child'];
2、获取iframe页面的document对象
// ie浏览器
var childDocument = myIframe.docuemnt;
// 其它浏览器
var childWindow = myIframe.contentWindow; // 获取iframe的window对象
var childDocument = myIframe.contentWindow.docuemnt; // 获取iframe的document对象
var childDocuemnt = myIframe.contentDocument; // 也是获取document对象 与 myIframe.contentWindow.docuemnt 相同
3、向id='box'设置内容
childDocument.querySelector('#box').innerHTML = 'xxxx';
二、子页面获取父页面
1、获取父页面的document对象
var parentDocument = window.parent.document;
2、如果iframe嵌套多个iframe,想直接取到最顶层的iframe
var selfDocument = window.self.document;
——————— ES5 API ————————
提供全局的JSON对象
1、JSON.parse(): 将字符串转成对象
2、JSON.stringify(): 将对象转成字符串
Array扩展
1、push(): 向数组最后插入内容 unshift():向数据最前面插入一项
2、pop(): 删除数组最后一项内容 shift(): 删除数组第一项内容
var arr = [1, 2, 3];
console.log(arr.pop()); // 3
console.log(arr) // [1, 2]
3、reverse(): 数组顺序颠倒
4、sort(): 排序
let arr = [1, 123, 23, 4, 125, 6, 2, 31];
arr.sort(function(v1, v2) {
return v1 < v2 // 从大到小排列
})
5、concat(): 两个数组进行合并, 也可以拷贝成为一个新数组,而不是带指向
var arrA = [1,2,3];
var arrB = arrA.concat();
arrB.push(5,6,7);
console.log(arrA); // [1,2,3]
console.log(arrB); // [1,2,3,5,6,7]
6、slice(开始,结束): 返回一个子数组, 如果结束参数不传为从开始取到最后的值
let arr = [125, 123, 31, 23, 6, 4, 2, 1];
let newArr = arr.slice(2, 5);
console.log(newArr, arr); // [31, 23, 6] [125, 123, 31, 23, 6, 4, 2, 1]
7、splice(): 用于替换、插入、删除
splice(1,3): 删除 下标1-3的数据
splice(3,0, 'insert'): 插入 在位置3一个'insert'字符串
splice(2,4, 'replce'): 替换 将2-4的数组用 'replce'符
8、indexOf(): 查找数组中指定的字位的位置,未找到返回-1
var arr = [1,2,3,4,5,6]; arr.indexOf(3); // 返回2
9、lastIndexOf(): 查找数组中指定的字位的位置,从后向前查找,未找到返回-1
* 迭代方法
10、every(): 每一项为true,结果返回true
// 数组中是否包含大于2的数
var num = [1,2,3,2,1];
var result = num.every(function(item,index,array) { // item: 1, index: 0, array: [1,2,3,2,1]
return (item > 2);
})
console.log(result); // true
11、some(): 有一项为true就不会往下执行,并返回true
var dwarfPlanets = ["ceres", "pluto", "haumea", "makemake", "eris"];
var result = dwarfPlanets.some(function(element) {
return (element === "pluto");
});
console.log(result) // true
5、filter(): 条件中返回true结果,重新返回一个新数组
var arr = [1, 2, 3, 2, 5, 7];
var result = arr.filter(function(item,index,array){
return (item > 2);
})
console.log(result); // [3, 5, 7];
6、forEach(): 遍历数组, forEach无法跳出循环, 只能通过try...catch
var arr = ['lulu', 'siguang', 'mama', 'baba'];
arr.forEach(function(item, index, arr){ // lulu 0 ["lulu", "siguang", "mama", "baba"]
console.log('name:'+item, index, arr);
})
7、map(): 将每次return的数据,最终组成一个数组返回
var srcColors = [
{r: 255, g: 255, b: 255 },
{r: 128, g: 128, b: 128 },
{r: 0, g: 0, b: 0 }
];
var newColor = srcColors.map(function(item, index, arr){
return item.r;
})
console.log(newColor); // 返回 [255, 128, 0]
8、reduce(上次执行的结果,当前值,当前索引,数组对象)、reduceRight(): 归并数组,每次循环都会返回上一次值和当前值
var val = [1,2,3,4,5];
var sum = val.reduce(function(prev, cur, index, arr){ // prev 第一次执行的是1, 第二次执行的就是上次1+2返回的结果
return prev + cur;
})
console.log(sum); // 15
对象属性和方法
1、__proto__: 对象实例与prototype之间的连接,原型链
2、prototype: 原型,公用的,节省内存开支,查找先去对象本身找属性和方法,如果没有到prototype下查找
3、constructor: 保存用于创建当前对象的构造函数名
4、toString()、valueOf()
5、delete: 删除对象属性
6、hasOwnProperty(propertyName): 判断对象属性是否在对象中(而不是prototype原型中) var obj = {name: 'aaa'}; obj.hasOwnProperty('name')
function Persion(){
this.name = 'siguang';
}
Persion.protoType = {
age: 35,
getName: function(){
return this.name;
}
}
let oPer = new Persion();
oPer.hasOwnProperty('name'); // true
oPer.hasOwnProperty('age'); // false
7、isPrototypeOf(object): 判断传入的对象是否是传入对象的原型
var o = new Object();
Object.prototype.isPrototypeOf(o)
8、instanceof: 用来判断一个构造函数的prototype属性是否在另一个检测对象的原型链上
class A {};
let oA = new A():
console.log(oA instancof A); // true
9、in: 属性是否在对象中能访问,返回true或false
function Persion(){
var sex = '男';
this.name = 'siguang';
}
Persion.prototype.age = 'haha';
var p1 = new Persion();
console.log('name' in p1); // true
console.log('age' in p1); // true
console.log('sex' in p1); // false;
10、Object.create(o, p): 可以创建一个干净的对象,给o对象创建一个prototype,如果p对象存在
var oA = Object.create(null); // 创建一个干净的对象,没有__proto__属性
var oB = {}; // 存储__proto__
function Car(desc){
this.desc = desc;
this.color = 'red'
}
Car.prototype = {
getInfo: function(){
return `color: ${this.color}, desc: ${this.desc}`
}
}
// 注意这里的name : {value: 'lulu'} 必须是对象,必须是value在根一个值,要不报错
var child = Object.create(Car.prototype);
child.desc = 'aaa';
child.color = 'bbb';
// 改变子类不会影响到父类
console.log(child);
var childCar = child.getInfo();
console.log(childCar) // color: bbb, desc: aaa
var oCar = new Car('ccc');
console.log(oCar.getInfo()); /// color: red, desc: ccc
1) Object.create()与new Object()的区别
var Base = function () {}
var o1 = new Base();
var o2 = Object.create(Base);
Object.create(null) 是创建一个空对象,这个对象不继承Object.prototype原型链上的属性或方法
11、Object.defineProperty(obj, prop, descriptor): 对象新增或修改一个属性会执行set()、get()方法来通知
参数: obj 目标对象 prop需要定义的属性 descriptor该属性拥有的特性,可设置的值有
descriptor的值:
value 属性的值,默认为 undefined。
writable 该属性是否可写,如果设置成 false,则任何对该属性改写的操作都无效(但不会报错),默认为 false。
get 一旦目标对象访问该属性,就会调用这个方法,并返回结果。默认为 undefined。
set 一旦目标对象设置该属性,就会调用这个方法。默认为 undeinfed。
configurable 如果为false,则任何尝试删除目标属性或修改属性以下特性(writable, configurable, enumerable)的行为将被无效化,默认为 false。
enumerable 是否能在for...in循环中遍历出来或在Object.keys中列举出来。默认为 false。
Example:
var obj = {};
Object.defineProperty(obj, 'name', {
get: function(){
debugger;
// this.name;
return 23;
},
set: function(newValue){
debugger
}
})
Object.defineProperty(obj, 'sex', {
get: function(){
debugger;
return '女';
},
set: function(newValue){
debugger
}
})
obj.name = 'sss'; // 调用set()
console.log(obj.name); // 调用get() 23
obj.sex = '男';
console.log(obj.sex); // 女
MVVM的核心:
<div>
<p>你好,<span id='nickName'></span></p>
<div id="introduce"></div>
</div>
<script type="text/javascript">
// 视图控制器
var userInfo = {};
Object.defineProperty(userInfo, "nickName", {
get: function(){
return document.getElementById('nickName').innerHTML;
},
set: function(nick){
document.getElementById('nickName').innerHTML = nick;
}
});
Object.defineProperty(userInfo, "introduce", {
get: function(){
return document.getElementById('introduce').innerHTML;
},
set: function(introduce){
document.getElementById('introduce').innerHTML = introduce;
}
})
userInfo.nickName = "siguang";
userInfo.introduce = "我是"+ userInfo.nickName +",我来自黑龙江,..."
</script>
https://segmentfault.com/a/1190000004346467
12、Object.defineProperties: 与defineProperty相同就是可以设置多个属性
let book = { year: 2004, edit: 1}
Object.defainProperyies(book, {
year:{
get: function(){},
set: function(){}
},
edit: {
get: function(){},
set: function(){}
}
})
13、Object.getPrototypeOf(object): 调用父类原型上的方法
// 定义一个父类
function PersonA(){
this.methodA = function(){
alert("a");
}
}
PersonA.prototype.methodB = function(){
alert('b');
}
// 定义一个子类
function Man(){
this.m1 = function(){
//getPrototypeOf只有继承父类的时候才可以调用其方法
Object.getPrototypeOf(this).methodA();
}
}
Man.prototype = new PersonA();
Man.prototype.m2 = function(){
Object.getPrototypeOf(this).methodB();
}
var man = new Man();
man.m1(); // a
man.m2(); // b
14、Object.keys(obj): 将对象obj下所有的属性的key,返回一个数组,用可以用它来判断是数组是否为空
Object.keys(obj).length 是否等于0
15、Object.getOwnPropertyDescriptor():
Date对象
var od = new Date(); // 创建当前中国标准时间 Thu Apr 27 2017 18:39:17 GMT+0800 (CST)
var od = new Date('2017-04-27 18:40:00'); // 指定时间 返回当前标准时间 Thu Apr 27 2017 18:40:00 GMT+0800 (CST)
1、getTime(): 返回当前毫秒数
2、setTime(): 以毫秒设置时期
var od = new Date();
od.setTime(12312312312332);
console.log(od); // Mon Feb 29 2360 22:45:12 GMT+0800 (CST)
3、getFullYear()、setFullYear(): 获取或设置年份
4、getMonth()、setMonth(): 获取或设置月份,值需要+1
5、getDate()、setDate(): 获取或设置日
6、getDay(): 返回星期几,值是0-6
7、getHours(): 小时
8、getMinutes(): 分钟
9、getSeconds(): 秒
Number对象
1、toFixed(): 将值格式化小数点后几位
String对象
1、length: 字符串长度
2、charAt(): 返回指定位置的字符 'abcde'.charAt(3) 'd'
3、chartCodeAt(): 返回指定位置的字符编码
4、concat(): 两个字符串拼接
5、split(): 将字符串以什么为分割,并返回为一个数组
截取
6、slice(begin,end): 截取字符串指定开始和结束位置的字符并返回, 可以接受负数
7、substring(begin,end): 截取字符串从开始到结束,
8、substr(begin, length): 返回一个指定开始到一个结束长度的字符
位置
9、indexOf(): 查找指定字符所在的位置
10、lastIndexOf(): 从后向前查找指定字符的位置
11、trim(): 删除前后空格 str.replace(/^\s*|$\s*/g, '');
12、toLocaleUpperCase(): 转成小写字母
13、toUpperCase(): 转成大写字母
正则
14、search(reg): 搜索正则中匹配字符的位置,没有返回-1
15、match(reg): 将匹配的正则返回一个数组
let text = "cat, bat, sat, fat";
let om = text.match(/.at/g); // ["cat", "bat", "sat", "fat"]
16、exec():
17、replace(reg, 替换字符): 替换指定字符
Math
1、min()、max(): 返回最小、最大值
舍入
2、ceil(): 向上舍入
3、floor(): 向下舍入
4、round(): 四舍五入
5、random(): 随机数 0-1之间
6、abs(): 绝对值
7、sin()、cos()
Global对象
encodeURI()、encodeURIComponent()
前端动画实现种类
1、纯粹的CSS3: transition/animation+transform(animate.css)
2、JS+CSS3 transition或者animation: 这里第一种一样,只是通过js里add class和remove class去增加或者移除对应的动画
3、纯粹JS控制时间轴: 第一和第二种都是自带时间轴,使用 setInterval / setTimeout / requestAnimationFrame 不断地修改 DOM 的 style 属性产生动画
整理
1、==、===
'100' == 100; // true; undefined == null; 因为JS会将两个值转换为相同类型
'100' === 100; // false
== 是先将数值转换后在进行比较,JS的一个设计缺陷、 === 不转换数值进行比较
2、 while和do...while
do...while 不管条件是否成立都会执行一次
var cont = 0;
do{
cont++;
console.log(cont); // 1;
}while(cont > 10);
3、break 退出循环、continue 退出当前循环开始下一循环
| http://kangax.github.io/compat-table/es5/ ES5兼容表
| https://developer.mozilla.org/zh-CN/docs/Web/API/Element/className API
| https://segmentfault.com/a/1190000000515151
| https://segmentfault.com/a/1190000005653355
| https://msdn.microsoft.com/zh-cn/library/dn342818(v=vs.94).aspx
| http://www.alloyteam.com/2016/05/javascript-timer/ js运行机制