原生---JavaScript
基础
基本知识
-
数据类型
-
数据类型
在js中有六种数据类型
(基本数据类型) String :在双引放单引 Number :包括整数与浮点数; 如何数值超过Number.Max_value则会返回infinity(无穷的数值类型);NaN也是一个数值类型。但他想表示这不是一个数值类型;对于精确度比较高的,千万不要使用JS运算,比如0.1+0.2得到的结果不准确。 Boolean Null :使用typeof检查是Object类型 Undefined 未定义,当我们声明一个变量,但没有赋值,输出时就会返加Undefined (引用数据类型) Object 对象
-
数据类型的判断函数
1-1、typeof 不可以判断null Object 1-2、instanceof 对typeof进行补充,用来判定Object(具体) 语法: 目标 instanceof 类型 ----判断左边是否是右边的实例 1-3、“===” 对typeof进行补充, 可以用来判断 null undefined
-
数据类型的转换
1、a.toString()与String(a)函数转字符串 ---前者有局限性,当a是null或Undefined类型时,会出现错误。 2、Number(a)函数转为数值类型 --null、boolean比较特别,他在一定方面代表的是数字,会转为数字。而不是NaN; 3、转布尔值的Boolean(a)函数(比较重要) --【数字类型】0,NaN【字符类型】空串 ""以及【null】【Undefined】【Object】上面除了Object都转为false
-
-
转意字符
\n 换行 对应HTML \t 制表(tab) 对应HTML
-
数值解析
-
数字解析
parseInt(a),parseFloat(a)两个函数 列举:0.123.4c.123 ---parseInt(a),解析得0,原理是从左到右只解析数字,遇非数字结束。除此还可以用来解析进制数parseInt(123,8) 深入应用: 如何获取var i=134;的百十个位数呢? 答:var bai=parseInt(i/100); var shi=parseInt((i%100)/10); var ge=i%10; 快速理解:先% 后parseInt()+"/"
---parseFloat(a),解析得0.123,从左到右解析数值,包括第一个小数点。
-
字符解析
以0x、0、0b开头分别代表什么进制数,分别是十六进制、八进制、十进制。 '\u + 16进制的unicode编码' '&# + 10进制的unicode编码 + 英文分号;'
-
-
运算
-
运算符+
不同数据类型进行加法运算, 主要看一对运算中是否有String、NaN.且优先级String>NaN, 举例:1+null+"abc"=1abc
-
非加运算符-*%
不管是何类型都转为Number运算。结果不是数字就是NaN; --原理是,从左到右将非数字类型转为数字类型如果转换失败,得到NaN,因为所有数值与NaN运算都是NaN,所以结束是NaN.
-
等号与自增自减运算
等号运算,“==”与“===”的区别在于是否会作转换,“===”是作全等运算。而“==”转换数据类型转换后进行全等运算。
自增有a++,++a 区别在于第一次代表的值。而后面他的值是一样的,都是自增后的值。 例举: var a=1; var b=1; console.log(a++,++b);//第一次,1 2 console.log(a,b);//第二次,2 2 (-- 略)
-
三目运算
Boolean ? A区:B区;三目运算符可以是语句块,也可以是某个值。 --补充:如果区是代码块最终变量是没能得到值的。
-
赋值运算
a=4与a[+-*/%]=b --前者是单纯的赋值运算,而后者是表达式赋值。 --后者:a+=b ==> a=a+b;
-
逻辑运算
首先将两边代码结果进行 ”布尔化“,根据&& (||), 进行从左到右找false(true)。如果找到返回位置上对应的内容,如果没找到返回最后一位的内容。
-
关系运算
a>b,类似运算中,会将他们数值化,如果都是字符类型则不会数值化,而是比较他们的Unicode编码。如果在数值化过程中转为了NaN,则最后结束是false.
-
-
语句
-
条件语句
if语句: 完整语句体 if(Boolean){
}else if(Boolean){
}else{
}switch语句 switch(i){ case a: 代码体1 break; case b: 代码体2 break; default: 代码块3 break; }
-
循环语句
共性:初始化表达式、条件表达式、更新表达式。
【循环语句while】while的结构是分散的。写法是从死循环到标准。 【循环语句for】for循环语句与while相比,for的结构是在一起的。而执行的顺序如下: for(1初始化表达式;2,5/,8/...条件表达式;4,7,...更新表达式){ 3,6,...代码块 }
-
补充
break(switch || 循环) ,continue专门用于循环
- 冒泡排序案例
-
var arr=[311,42,33,5,21,6,7,312]; console.log(arr); for (var i=1;i<=arr.length-1;i++){//重在体现循环次数(前两位不用比较-->所以比较次数是length-1) for (var j=1;j<=arr.length-i;j++){//如下图(j=1两个数比较的第二个数,arr.length-i是循环次数的表达式) if(arr[j-1]>arr[j]){//交换逻辑 var sub=arr[j-1]; arr[j-1]=arr[j]; arr[j]=sub; } } } console.log(arr);
-
-
对象
-
认识
存储不同数据类型的容器, 可以向里面添加任意的数据类型,包括对象,函数,数组与其它对象。
-
工厂创建
工厂模式 将公共方法存到原型对象中,从而避免每创建一个对象就创建一个属性,来节省内存空间。 function Pro(name,age){ this.name=name; this.age=age; Pro.prototype.setName=function (newName){ this.name=newName; } } var pro=new Pro("小庄",23); 补充: this代表新创建的对象
new就是调用了构造函数进行创建,其执行流程: 1、立刻创建一个新的对象, 2、将新建的对象设置为函数中this,在构造函数中可以使用this来引用新建的对象 3、逐行执行函数中的代码//由我们书写,其它步骤不可见 4、将新建的对象作为返回值返回
使用同一个构造函数创建的对象,我们称为一类对象,也将一个构造函数称为一个类。通过一个构造函数创建的对象,称为是该类的实例。
-
添加
用方法添加 --obj.nama ="<value>"; obj["name"]="<value>"; 用快捷表达法添加 { name:123, "123":345 } 注意向对象添加的属性名可以不用符合标签符命名规则,但添加的方式需要用引号括起。
-
读取
普通 obj.element 特殊(对应添加) obj["123"]
-
查找
检查obj是否包含有element属性 var ifs=("element" in obj);
-
删除
删除obj中的element属性 dellete obj.element
-
遍历
枚举 for(var key in obj){ arr.push(key+"="+obj[key]); }
-
-
原型对象
-
认识
原型对象: 不管在Object对象,函数(包括Function函数),还是实例对象中,都有原型对象。且他们是存在有关系的。(请看附件)
-
属性的查找
关于检查: hasOwProperty:用来检查对象本身是否含有指定的属性 pro.hasOwnProperty("name") "属性" in 对象.用来检查本身及其原型是否包含指定属性。 举例: function Pro(name){ this.name=name; } var pro=new Pro("孙悟空"); pro.proto.age=23; console.log(pro.hasOwnProperty("name")); console.log("age" in pro);
-
-
函数
-
认识
函数本身也是对象,里面包含了可执行的代码。函数用来实现特定的功能。 分类: (函数本身也是对象) var at3=new Function("console.log('原始');"); at3(); (有函数名) function fun1(){
}
(无函数名)
有接收:
var fun=function(){
}
无接收(立即执行函数):
(function(a){
})("a")
对象中的函数
--方法 -
作用域
全局变量作用域生命周期是由网页打开到关闭。 而函数变量(局部)作用域从调用到调用结束。
-
this
在函数中,用对象调用,this就是该对象。 在函数中,用函数的返回值调用,this是Window. 在构造函数中,this代表的是新创建的对象。
改变this: Per.call(obj,2,3);//依次传参 Per.apply(obj,[2,3]);//以数组的形式传参
-
类数组arguments
arguments,在函数中arguments包含了传进来的所以参数,而不限于形参。 arguments是一个类数组,我们可以获取里面的包含的参数。
我们也可以将这个类数据转为真正的数组。
var args = Array.prototype.slice.call(arguments);除此 我们还可以利用其cellee属性得到最近最近外围的函数。来实现递归。 var num=1; function fu(){ console.log(num++); arguments.callee();//相当于fu()
} fu();
-
-
垃圾回收
当一个对象,没有变量指向它的时候,js垃圾回收器就会自动 回收这些内存资源。
内置对象
-
数组
-
认识
数组是用来存储数据的,可以存储任意的数据类型。可以将其看作一个容器。
-
基本使用
数组是Array对象,快速用[]快速创建。 向后添加数据 arr[arr.length]="new 替换方法 arr.splice(开始索引 , 向后数量 ,"新数组属性");
- 数组的方法:join() 方法也可将所有数组元素结合为一个字符串,参数是连接符。push() : 向数组后面添加新的元素(比如 arr.push(key+"="+obj[key]);)。
-
数组的遍历
两种方法: var arr=[1,2,3,4]; 专门用于遍历数组的forEach方法(不可中途终止遍历) arr.forEach(function(val,ind){ console.log("索引="+ind+",值="+val); }); 使用性更广的for循环遍历(可中途终止遍历) for(var i=0;i<arr.length;i++){ console.log("索引="+i+",值="+arr[i]); if(i==2){ break; } }
-
-
时间对象Date
获取时间对象 var auto=new Date();//获取当前时间 var din=new Date("05/20/2020 13:14:00");//自定义一个时间 时间对象的一些方法 getDate() 以数值返回天(1-31) getDay() 以数值获取周名(0-6) getFullYear() 获取四位的年(yyyy) getHours() 获取小时(0-23) getMilliseconds() 获取毫秒(0-999) getMinutes() 获取分(0-59) getMonth() 获取月(0-11) getSeconds() 获取秒(0-59) getTime() 获取时间(从 1970 年 1 月 1 日至今) console.log(auto.getTime());//获取指定时间的时间戳 var start=Date.now();//获取现在的时间戳。
-
数学对象Math
Math对象(数学工具类) Math.floor(x) 的返回值是 x 下舍入最接近的整数: Math.ceil(x) 的返回值是 x 上舍入最接近的整数: Math.round(x) 的返回值是 x 四舍五入为最接近的整数: Math.random() 返回 0(包括) 至 1(不包括) 之间的随机数: 获取X到Y的随机整数 Math.floor(Math.random()*(y-x+1))+x;
-
包装类
这个内容只需要理解即可,因为它是由底层使用的。 关于包装类: 为什么基本数据类型也可以用toString方法? 为什么我们可以基本数据类赋值,却调用不了? 因为当我们用基本数据类型调用一些方法时,底层会自动将基本数据类型转为对象。 a.toString()==== var b=new Number(a); console.log(b.toString());
-
操作字符的一些方法
根据索引获取指定字符 ut.charAt(1); 连接字符串 ut.concat("567","890"); 截取字符串中的内容 ut.slice(1,-1); [起来s] 将字符串进行拆分为数组 name.split(","); [cplit]
-
正则表达式
test方法:检查右边的字符是否符合左边的正则 RegExp对象:动态修改正则表达式, new RegExp("\b"+cn+"\b");,会返回一个正则表达式对象
str.match(/[a-z]/ig); match方法将在左边满足的字符,装箱为一个数组。所以需要用全局g.
(ig免忽略大小写且进行全局匹配,还有m执行多行匹配。)"".replace(//,"")利用正则进行替换字符
(对字符的描述)
[abc]、[A-z0-9],
\w 查找数字、字母、_
\d 查找数字。
\s 查找空白字符。
\b 匹配单词边界。
(字符量词)
{n,m}左边一个字符或一个()组出现n到m次,{m}出现m次,{m,}出现m次以上。
+至少一个==={1,}
*有没有都可以{0,}
?有或没有
(字符位置)
/^n/前面不能再有字符,
/n$/后面不能再有字符
/^n$/完全符合正则表达式,即:只能是str="n";才满足。
DOM
-
事件
-
认识
我们给某个对象绑定事件,我们可以写触发后要执行的代码。 有点击,双击,移入,移出,键盘,滚轮等事件。
-
加载事件
onload事件:由于文档加载自上而下的原因,我们需要用到这个事件,以免当我们对文档进行操作时,其对象不存在(还未加载 ) 应用 window.onload=function(){ //当文档加载完成后,会自动触发执行 }
-
焦点事件
【焦点事件】 onfocus得到焦点 onblur失去焦点事件
-
键盘事件
键盘事件
onkeydown键按下事件
onkeyup键松开事件 识别按下是哪个键: 在键盘事件触发后,获取传入的参数event,可以根据event.keyCode==键码,根据特殊的 event.altKey,event.shiftKey等, 多键识别:我们可识别特殊键+非特殊键 取消默认键盘行为 键盘事件触发后,return false;时,在输入框时输入将无法正常使用。
-
单击/双击事件
单击事件 up.onclick=function(){ //要执行的代码 }; 双击事件 up.ondbclick=function(){ //要执行的代码 }
-
滚动条事件
onscroll 事件:当我们滑动滚动条时触发 使用: info.onscroll=function(){} 获取滚动条的一些信息: //info.scrollHeight是总高度 //info.scrollTop当前滚动条到top的长度 //info.clientHeight可见页面高度 扩展: 组件可用性:disabled=true|false;
-
滚轮事件
滚轮事件
box.onmousewheel = function(event) {//滚动触发 event = event || window.event; if (event.wheelDelta > 0 || event.detail < 0) {//判断是否是下滚动且兼容 box.style.height = box.clientHeight - 10 + "px"; } else { box.style.height = box.clientHeight + 10 + "px"; } event.preventDefault && event.preventDefault(); //解决连带滚动条滚动问题,&&当可用时执行 return false; //取消默认行为(滚动默认连动总页面滚动) } //解决滚轮事件浏览器兼容问题,如果是火狐,它是不支持onmousewheel事件的, bind(box, "DOMMouseScroll", box.onmousewheel); function bind(obj, eventStr, callback) { //事件监听兼容函数 if (obj.addEventListener) { obj.addEventListener(eventStr, callback, false); } else { obj.attachEvent("on" + eventStr, function() { callback.call(obj); }); } }
-
-
节点
-
获取节点
【获取节点】 (document) document.getElementById("bt");//根据Id获取节点 getElementsByTagName("li");//演示根据标签名获取组属性 document.getElementsByName("user");//演示根据name的属性获取组属性 var bufu=document.querySelectorAll("#imgbox"); //根据css选择器获取组节点 【获取关系节点】 fu.children;//获取全部子属性节点 down.parentNode;//获取父节点 down.previousElementSibling;//获取前一个兄弟节点 down.nextSibling;//获取后一个兄弟节点
-
创建节点
【创建节点与节点关系】 var but=document.createElement("button");//创建一个属性节点 var btext=document.createTextNode("最后一张"); //创建一个文本节点(可在父节点用innerHTML代替) but.appendChild(btext);//将新节点插入指定节点下
bufu.insertBefore(but,down);//将新的节点插入指定的子节点之前。
bufu.replaceChild(but,down);//将新节点代替旧节点
but.parentNode.removeChild(but);//删除子节点 -
读取节点
读取节点的属性与内部HTML代码
bt.value;//读节点属性。 (class属性是保留字,需要.className去读取) bt.innerHTML;//读内部HTML代码 bt.innerText;//获取除标签外的全部内部文本
-
应用
-
修改样式
为属性设置内部样式属性 obj.style.backgroundColor="red"; 除此,我们还可以通过修改Class值来添加或删除一组样式。
-
读取样式
利用下面的方法可以读取现在正在显示的样式
function getStyle(obj,name){//读取现在的样式属性值 if(window.getComputedStyle){ //大部分浏览器支持 return getComputedStyle(obj,null)[name]; }else{ //只有IE8支持 return obj.currentStyle[name]; } }
-
-
-
捕获与冒泡
如果以父子关系依次相关联的,当子事件被触发时,以W3C的标准,分为从document到目标的捕获阶段,再到从目标向外的冒泡阶段。如果我们想在捕获时执行,需要在事件监听器 obj.addEventListener(eventStr,callback,false);
-
事件的冒泡
子元素事件被触发会自动触发相同事件的父元素。
取消冒泡 var maot = document.getElementById("maoTest"); //取消冒泡 maot.onmousemove = function(event) { event.cancelBubble = true; //隔板生效 }
-
事件的委派
每个事件被触发后执行的函数都可以接收一个参数,他封装了一些信息,如由于事件的冒泡,我们不确定是谁触发的自己,这时参数对象有一个target属性,可以得到最先被触发的那个对象。
-
-
自定义方法
-
拖拽函数
使用方法:只需传入要移动对象即可。
function Tuo(box){ //拖拽函数 //给box添加一个鼠标按下事件 box.onmousedown=function(event){ //获取点击时在box中的相对位置x2,y2 var x2=event.clientX-box.offsetLeft;// var y2=event.clientY-box.offsetTop; //给document添加一个拖拽事件 document.onmousemove=function(event){ //将传进来的event参数加强兼容性 event=event || window.event; //获取鼠标在document中的位置 var x=event.clientX; var y=event.clientY; //修改box中的top与left属性 box.style.top=y-y2+"px"; box.style.left=x-x2+"px";
}
document.onmouseup=function(){//当松下后,关闭移动与松下事件
document.onmousemove=null;
document.onmouseup=null;
}
return false; //解决全选后拖拽不了的问题}
}
-
方向键移动函数
box :是要移动的对象 a :是物体移动的速度
function boxmove(box, a){ var fan;//移动的方向 //当按下一个键时,改变方向变量fan的值。松开时设置为空。 //即我们按下时就朝着设置好的方向移动,松开后没有移动方向。 document.onkeydown=function(event){ fan=event.keyCode; document.onkeyup=function(){ fan=null; }
}
var yidon=setInterval(function(){
switch(fan){
case 37:
box.style.left=box.offsetLeft-a+"px";
break;
case 38:
box.style.top=box.offsetTop-a+"px";
break;
case 39:
box.style.left=box.offsetLeft+a+"px";
break;
case 40:
box.style.top=box.offsetTop+a+"px";
break;
}
},30);}
-
BOM
-
认识BOM
浏览器对象模型BOM
-
Navigator
【Navigator】 --获取浏览的信息,识别不同浏览器 var ua=navigator.userAgent; if(/firefox/i.test(ua)){ alert("你是火狐"); }else if(/chrome/i.test(ua)){ alert("你是谷歌"); }else if(/msie/i.test(ua)){ alert("你是IE"); }else if("ActiveXObject" in window){ alert("你是IE11,枪毙了你~"); }
-
Location
【Location】 --代表浏览的地址栏 //执行后会跳转到指定链接上 location.assign("http://www.baidu.com");
//执行后会清除缓存 location.reload(true);
//执行后会替换当前,且不可逆。 location.replace("http://www.baidu.com");
-
History
【History】 --当前容器的历史记录 history.back();//当前窗口的上一个页面 history.go(-2);//跳转到前第二个页面 history.forward();//当前窗口的下一个页面
-
screen
【screen】 --获取显示器的相关信息
-
定时器&超时调用
定时器 setInterval(function(){
},<循环调用时间>);
clearInterval( );//关闭指定的定时器 #如果想继续开启定时器,你需要将这个定时器用一个函数包装,如果你是在外部关闭定时器,需要将这个定时器声明出函数外。 -
超时调用 setTimeout(function(){
},<调用时间>);
clearTimeou //关闭指定的超时调用-
自定义的方法
/* 1、动画函数 obj:目标属性 speed:改变的速度 target:改变的幅度 type:top\left\width\height fun:回调函数,动画执行完时调用
*/ function move(obj, speed,target,type,fun){ console.log("你调用了jsTools中的move动画函数~"); function getStyle(obj , name){//根据样式名获取样式值 if(window.getComputedStyle){ return getComputedStyle(obj,null)[name]; }else{ return obj.currentStyle[name]; } } //函数主体 clearInterval(obj.ding); if(parseInt(getStyle(obj,type))>target){ speed=-speed; } obj.ding=setInterval(function(){ var oldValue=parseInt(getStyle(obj,type)); var newValue=oldValue+speed; if((speed<0 && newValue < target ) ||( speed>0 && newValue > target) ){ newValue=target; obj.style[type]=newValue+"px"; clearInterval(obj.ding); fun ?fun(): console.log("未传入回调函数");//执行回调函数 }else{ obj.style[type]=newValue+"px"; }
},30);
}
/*
2、添加或删除指定Class值
obj:目标属性
cn:是要添加或移除的Class值
*/
function hasClass(obj,cn){//有添加,无删除Class指定值
var ze=new RegExp("\\b"+cn+"\\b");
if(ze.test(obj.className)){
obj.className=obj.className.replace(ze,"");
console.log("已替换");
}else{
obj.className+=" "+cn;
console.log("已添加");
}
}
function AddClass(obj,cn){//没有添加
var ze=new RegExp("\\b"+cn+"\\b");
if(! ze.test(obj.className)){
obj.className+=" "+cn;
}
}
function RemoveClass(obj,cn){//有移除
var ze=new RegExp("\\b"+cn+"\\b");
obj.className=obj.className.replace(ze,"");
}/* 3、二级菜单伸缩动画函数 使用说明:给具有指定结构的二级菜单栏添加伸缩动画效果 <div id="my_menu" class="sdmenu"> <div class="collapsed"> 在线工具 图像优化 ... </div> <div class="collapsed"> 支持我们 图像优化 收藏夹图标 .... </div> </div>
/ function mocc(boxId){ var box=document.getElementById(boxId); //获取二级菜单主体下的span var title=box.getElementsByTagName("span"); var index; //遍历span for(var i=0;i<title.length;i++){ title[i].index=i; title[i].ofno=false; //为每个span绑定一个单击响应函数 title[i].onclick=function(){ //得到当前span的父节点,与其下一个兄弟 var Tparent=this.parentNode; var Tsibling=this.nextElementSibling; if(Tsibling){ //分别得到展开前后的动态值 var init=Tparent.querySelector("span").offsetHeight; var end=Tparent.querySelectorAll("a").length(Tsibling.offsetHeight)+init; //根据现在的状态,给等下要操作的目标长度赋值 后修改操作后的状态 var mo=this.ofno ? init :end; this.ofno ? (this.ofno=false) : (this.ofno=true); move(Tparent,6, mo,"height",function(){ }); }
}
}
}
-
高级
对基础知识的深入了解
-
函数参数
我们给函数传入参数时,就相当于在函数作用域中声明了一个变量。
-
资源的回收
自动释放:生命周期完后 回收:没有变量指定这个内存地址后,这块内存就会被回收器回收。
-
[]在对象中的应用
var obj={ "a-b":123, "123":"ab" } console.log(obj["a-b"]); //特殊属性名时 var name="a-b";//属性名不确定时 console.log(obj[name]);
-
回调函数
什么是回调函数? ---你定义了,没有调用,但最后执行了。 比如:事件 、定时器
-
IIFE
IIFE ——立即执行函数的作用 ---不会污染全局命名空间,隐藏实现。
-
isAdd分号?
关于加不加分号问题 ---小括号、中括号 前不加就会报错。 var a=3 (function(){alert(123)})() 或 var a=3 [1,2]forE....
高级部分
-
原型对象
-
再认识
函数的原型对象默认指向一个空对象,里面默认有下面这两个属性。 constructor //指向自己this proto //原型的原型对象
-
显式原型与隐式原型
显式原型对象与隐式原型对象 函数prototype 显式原型对象====对应实例的 proto 隐式原型对象
创建函数时,Fn.prototype={} 创建实例时,this.proto=Fn.prototype
-
原型链
-
原型链的继承
-
-
变量提升与函数提升
*变量提升与函数提升 变量提升,执行之前先声明,但未赋值 函数提升,在语句之前已声明,完整存在
理解:在变量执行之前,就可以访问到了,但它的值是undefined。在函数执行之前,就可以调用到了。因为存到了上下文中栈中了。
且先执行变量提升再执行函数提升!!
注意:就算是if语句中的变量,也是会自动进行变量提升的。 -
作用域
*作用域 ——迷惑型题目 题1: var a=4; function fun1(){ console.log(a); } function fun2(){ var a=6; fun1(); } fun2(); 结果: 4 ,是根据自己身所在位置进行查找的,而不是根据关系查找。 题2 var obj={ tet:function (){ console.log(tet); } } obj.tet(); 结果是:报错,找不到 总结:是根据上下文栈块逐层查找的。
-
执行上下文
-
分类
JavaScript 中有三种执行上下文类型。 全局执行上下文 — 这是默认或者说基础的上下文,任何不在函数内部的代码都在全局上下文中。它会执行两件事:创建一个全局的 window 对象(浏览器的情况下),并且设置 this 的值等于这个全局对象。一个程序中只会有一个全局执行上下文。 函数执行上下文 — 每当一个函数被调用时, 都会为该函数创建一个新的上下文。每个函数都有它自己的执行上下文,不过是在函数被调用时创建的。函数上下文可以有任意多个。每当一个新的执行上下文被创建,它会按定义的顺序(将在后文讨论)执行一系列步骤。 Eval 函数执行上下文 — 执行在 eval 函数内部的代码也会有它属于自己的执行上下文,但由于 JavaScript 开发者并不经常使用 eval,所以在这里我不会讨论它。
-
执行上下文栈
-
执行上下文栈.jpg
-
-
-
-
产生的条件
函数内嵌套有函数, 内函数引用了外函数的属性(变量或函数), 并且外部函数被调用执行;
(function Pro(){ var a=Math.random(); window.mm=function (x,y){ return Math.floor(y-a*(y-x)); } })()//外部函数调用
-
自定义JS模块
js自定义模块 将代码封装在一个JS文件中,有特定功能。向外暴露一些行为函数。 1、私有数据 2、操作数据的函数 3、向外暴露对象(给外部使用的方法)
var myModule = (function(){
var var1 = 1;
var var2 = 2;
function func1(){
...
}
function func2(){
...
}
return {
func1: func1,
func2: func2
};
})(); -
终极面试题
终极面试题
function fun(n,o){ console.log(o); return { fun:function (m) { return fun(m, n); } } } var a=fun(0).fun(1).fun(2).fun(3);
解析:a=fun(0) 时,它的返回值中含有闭光,值为0 ...fun(1) 时,它的返回值中含有闭光,值为1 .....f
-
-
内存的溢出与泄露
*内存溢出与内存泄露 你需要的内存大于剩余的内存空间,就会导致内存溢出。从而报错。 内存泄露:不合理地占用内存资源,而不及时地释放 ,如,定时器、函数中变量的错误声明为全局变量等,都会导致内存泄露从而使内存溢出。
-
借用构造函数
构造函数借用构造函数:得到属性 function Fun1(age){ this.age=age; } function Fun2(name,age){ this.name=name; Fun1.call(this,age);//开始借用 }
-
单线程与多线程
-
认识
*单线程与多线程 有的程序是单进程有的是多进程的,而多进程数据一般是不共享的,且每一个进程可能有多个线程。 JS是单线程的:警告框可以暂停主线程的执行,如果是多线程会带来很复杂的同步问题。
-
Web worker多线程技术
*Web Worker Web Worker,作为JS中的多线程技术,主要用来处理耗时较长的程序。
主线程(老板)---调用*.js文件
var wo=new Worker("fine.js");
wo.postMessage(1);//向分线程发送数据
wo.onmessage=function (e){
//接收分线程传过来的数据
console.log(e.data);
}
分线程(工人)---*.js
var onmessage=function(event){
var jout=++(event.data); //接收主线程传过来的数据
postMessage(jout );//向主线程发送数据
}
-
-
回调队列
-
认识
回调队列
初始化代码执行完后,才会执行回调代码,而执行回调代码时先将它们添加到对应的模块中,当条件满足时,如点击了,定时器的时间到了,就会将其添加到回调队列后面进行排队,然后先进先出。
var yfd=document.getElementById("yfd");
yfd.onclick=function (){//点击后,会在后面添加到回调队列中。
console.log("点击事件:进入回调队列并执行了~");
}
setTimeout(function (){
console.log("外部定时器已开始");
setTimeout(function (){console.log("内部定时器结束了")},3000);//会添加对应模块中,3秒条件满足后,会在后面添加到回调队列中。
console.log("外部定时器已结束,此时如果你不点击回调队列中没有东西。但已新添加了一个定时器,等下不管你有没有点击,3秒后都会添加到事件队列中");
},20);
console.log("初始化执行完了。。");
*Web Worker -
图解
-
var arr=[311,42,33,5,21,6,7,312]; console.log(arr); for (var i=1;i<=arr.length-1;i++){//重在体现循环次数(前两位不用比较-->所以比较次数是length-1) for (var j=1;j<=arr.length-i;j++){//如下图(j=1是下图的1,arr.length-i是下图循环次数的表达式) if(arr[j-1]>arr[j]){//交换逻辑 var sub=arr[j-1]; arr[j-1]=arr[j]; arr[j]=sub; } } } console.log(arr);