Varcur=arguments[i];//argumets是类数组只能用argument[i]这样的形式来获取
Cur=Number(cul);
If(!
isNaN(cul)){}
Total+=cul;
}
Returntotal;
}
闭包:
函数执行的时候,会形成一个新的私有的作用域来保护里面的变量不受外界的干扰,我们把这种保护机制,叫做闭包!
外面想用什么就直接在函数里面return什么,函数执行完成的整体就是这个值;
1,如果一个方法没有写return的话,函数默认返回的值是undefined在函数体中return后面的代码不在执行!
2,控制函数体中的代码执行到指定位置就结束
函数的种类:
实名函数,匿名函数
上面的都是实名函数;
匿名函数:
函数表达式,把一个匿名函数的定义部分当作一个值赋值给一个变量或者一个元素的事件!
Varfn=function(){}
Fn();
自执行函数--定义和执行一起完成了!
(function(){})();
~function(){}();!
function(){}();+function(){}();-function(){}();
都是我们的自执行函数
(重点)基本数据类型和引用数据类型的本质区别
Varnum1=11;varnum2=num1;把num1代表的值给了num2这个变量
Num2++;相当于在num2=num2+1也就是在自己原有的基础上加1;也相当于num2+=1;
Console.log(num1);---------------------输出11
Varobj={name:
”zhufeng”};
Varobj1=obj;
Obj1[“name”]=”hewenbang”;
Console.log(obj[“name”]);-----------------------输出hewenbang
--------发现基本数据类型没有跟着发生改变,而引用类型跟着发生了改变
基本数据类型和引用数据类型的本质区别
------基本类型操作的是值,而引用类型操作的是新空间的地址
----------基本数据类型是吧值直接给的变量。
接下来的操作过程中,直接拿这个值进行操作,可能俩个变量存储的值一样,但你的是你的,我的是我的没有任何的影响,其中一个改变,另一个没有任何影响!
(全在栈空间)
--------引用数据类型1.定义一个变量2.开辟一个新的堆内存空间,然后把属性名和属性值保存在这个空间,并且有一个空间地址3.把空间的地址给了这个变量,变量并没有存储这个数值,而是存储的对这个空间的引用地址4.接下来我们把这个地址又给了另外一个变量,另外一个变量存储的也是这个地址,此时俩个变量操作的是同一个空间5.其中一个改变了空间的内容,另外一个也跟着改变了
JS中检测数据类型的方式:
Typeof运算符instanceof运算符constructorObject.prototype.toString.call();
Console.log(typeof“zhiufeng”);
Typeof用法:
typeof要检测的值
返回值:
是个字符串包含数据类型字符“string”“number”“boolean”“object”“function”“undefined”
Typeofnull-----------------“object”
Typeof的局限性:
不能具体检测object下细分的类型,检测放回的是object
操作语句部分
三个判断语句:
ifelse用的最多的可以解决js当中所有的项目需求
三元运算符应于于简单ifelse操作
Switchcase运用于不同值情况下的不同操作
Varnum=10;
If(num<0){
Console.log(“负数”);
}elseif(num>0&&num<=10){
Console.log(“0-10之间”);
}else{
Console.log(“大于10”);
}
If条件里面可以是大于小于等于也可以是一个值(判断一个值是真是假)也可以多个小条件组成||(条件一个成立即可)&&(条件都成立才行)
三木运算符
Varnum=12;
Num>=0?
num=13:
num=-8;
?
号是条件成立时执行的:
是条件不成立时执行的当不需要执行的时候用void0;来占位
Switchcase
Switch(num){
Case1:
Alert
(1);
Break;
Case2:
Alert
(2);
Break;
Default:
Alert(“我是NaN”);
}
每一中case相当于===在比较,一定要注意数据类型,
循环语句:
For循环
四部曲:
1,设置初始值vari=0,2,设置循环执行条件i<6;3,执行循环体中的内容{}包起来的部分4,每一轮循环完成后都执行我们i++累加操作
For(vari=0;i<6;i++){
Console.log(“hah”);
}
Break:
在循环体中出现break整个循环就整体的结束了,i++最后的这个累加操作也不知行了,
Continue:
在循环体中出现continue当前这一轮的循环就结束了,继续下一轮循环,i++操作继续执行
在循环体中遇到这俩个关键字,循环体中后面的代码就不执行了
For(vari=0;i<10;i++){
If(i<=5){
i+=2;
continue;
}
i+3;
break;
}
Console.log(i);--------------9
Forin循环
就是用来循环对象中的属性名和属性值的对象中有多少键值对,我们就循环多少次
顺序问题:
首先循环键名为数字的属性值,按照从小到大,剩下的按照我们写的顺序循环
Varobj={
Name:
”hewenbagn”,
Age:
”15”;
Height:
”20”;
}
For(varkeyinobj){
Console.log(obj[key]);
获取属性值:
在forin循环中只能通过obj[key]来获取属性值
}
数组Array
Vararr=[1,2,3,4]----------字面量创建方式
Vararr=newArray();实例创建方式
Console.dir(arr);看数组的详细信息,包含我们数组中常用的几个方法(找到—prototpe__展开这个里面提供了我们数组中常用的方法)
Varary=[“zhufeng”,”liji”,28,true,null,undefined,{},functionfn(){}];
1,//数组是由多个项组成的,每一项之间用逗号隔开,并且每一项存储的数据类型,可以是任何的数据类型!
2,数组也是对象数据类型,对象数据类型是由属性名:
熟悉值组成,健名我们在数组中我们称之为索引ary[索引]就是获取数组中地索引加1项的内容
3,获取当前数组的长度ary.length
4,如果我们写的索引超过了总长度返回的结果是undefined
5,在操作数组的时候我们一般用for循环来操作
数组中常用的方法:
学习数组方法注意事项:
1,方法是做什么用的,实现了什么功能!
2,传递的参数是什么
3,返回值是什么
4,原数组是否发生了变化
关于数组的增删改查
Push----向数组的末尾添加新的元素(一个或者多个),传递的参数就是要添加的元素,返回值内容是添加后新数组的最终的长度原有的数改变了
Unshift向数组的开头添加新的元素(一个或者多个),传递的参数就是要添加的元素,返回值内容是添加后新数组的最终的长度原有的数组也改变了
Ary.push(“14”,”15”);、
Splice(n,0,x)向数组的某个位置添加新的内容,
从索引n开始,删除0个内容,把索引x放在索引n的前面,返回的是一个空数组,原有数组发生了改变
Splice(n,m)从索引n开始(包含n)删除m个元素删除数组中指定的某些项把删除的内容当做一个新的内容返回,原有数组发生了变化
Splice(n,m,x)把原有数组中的某些项进行替换先进行删除,然后用x替换,从索引n开始,删除m个元素,用x替换原来的,把删除的内容当做一个新数组返回,原有数组发生了变化
Splice(0,0,x)相当于unshift
Splice(ary.length,0,x)相当于我们的push
Pop删除数组最后一个返回的是删除的那一项原有数组发生改变
Shift删除数组最后一个返回的是删除的那一项,原有数组发生改变
数组的查询和复制
Slice(n,m)从索引n开始包含n找到索引为m数不包含m然后把找到内容作为一个新的数组返回,原数组没有发生变化
Slice(n)索引n开始一直查找到末尾,把找到数组返回原有数组不发生变化
Slice(0)将原有的数组原封不动的复制一份这属于数组的克隆
Concat也可以实现数组的克隆
Ary.concat();原来的数组也不改变相当于slice(0)
Concat是实现数组的拼接的
Vararr=[1,2];varar2=[3,4];
Arr.concat(ar2);
将数组转化为字符串
toString把数组中的每一项用逗号隔开,组成一个字符串原有数组不变
join(“分隔符”)把数组中的每一项拿出来,按照指定分隔符隔开
实现数组中数字的求和
Eval将指定的字符串变成真正的表达式来执行
5,数组的排列排序
Reverse让数组到过来排列
Sort排序sort(function(a,b){returna-b;});
A代表每一次循环的时候当前这个项,b是后面的这个项;
Returna-b;当前项减去后一项如果大于0说明当前项大于后一项这样的话就交换位置
第五组:
常用但不兼容:
ForEachindexOfmap
正式课总结
第一周预解释和作用域
在刚开始加载页面的时候,浏览器会天生自带一个供我们当期JS代码执行的环境,我们把这个环境称之为“栈内存”,我们也可以叫他为作用域
而且开始加载页面的那个作用域称之为全局作用域(window)
在全局作用域下声明的变量叫做全局变量,(功能用函数)
预解释是发生在当前作用域下的,刚开始只是声明或者定义全局下的var或者function
只有funciton里面的不是全局的
带var和带function关键字的,进行预解释的时候是不一样的,
var只是提前声明
function在预解释的时候就声明和定义
一个function在代码执行之前(预解释的时候)就把声明和定义完成了,在接下来执行代码的过程中,如果遇到了函数定义的那块代码直接的跳就OK了
函数执行可以写在任何位置,原因是定义的这个操作在预解释就完成了
函数的执行 sum(1.2.3)会形成一个新的私有作用域(栈内存:
执行代码和存储基本数据类型),进来之后第一步首先进行的就是把这个私有作用域预解释
其次代码执行
在函数的这个私有作用域定义的变量都是私有的变量,形成的这个作用域保护里面的私有变量不受外界的干扰,我们把这种机制叫做闭包!
函数执行一次形成一个新的私有作用域,上述的步骤重复一次
//预解释是发生在当前作用域下的,
一般情况下,函数在每一次执行完成,函数新形成的作用域都自动销毁
JS当中只有window和funciton会产生作用域:
预解释是一种毫无节操的变态机制
1.预解释只发生在当前作用域下
2.不管条件成立与否,都要进行预解释
3.预解释时发生在=的左边,等号的右边不进行预解释
4.只有预解释只发生在同一个JS脚本里面
5,;(function(){})();自执行函数不进行预解释(在全局下不把()包起来的那个function预解释,但是执行的时候形成的私有作用域的进行预解释)
6,函数中return后面的代码也要进行预解释
7.在预解释的时候,如果发现重名了,不重新声明,但要重新定义
fn();//预解释好无节操
varfn=12;
fn();//12();Error:
numberisanotfunction;
functionfn(){
console.log("预解释好无节操");
}
------预解释是发生在当前作用域下的
如何的判断他的上一级作用域
看存储这个函数的堆内存在哪一个作用域下(比如这个作用域是A),那么这个函数执行的上一级作用域就是A
如何判断是私有的还是全局的
在一个函数中只有预解释声明过的和形参是私有的,否则的话往他的上一级作用域找,如果上一级也没有则继续找,一直找到window作用域
在JS当中,如果当前行JS报错,下面代码都不执行了,(前提是:
没有进行异常捕获处理)
全局作用域下才有的这样一个机制
我们return的是一个堆内存地址,当前这个堆内存在这个fn这个作用域
一个大函数,返回的是引用数据类型(经常是function)那么当前这个大的函数形成的作用域就不能销毁(里面的私有变量也一直存在)
一个大函数,套一个小函数给这个小函数绑定点击事件这种大的作用域也不销毁
//varname="china";
//varage=5000;
//;(function(name,age){//是自执行函数的俩个形参变量
////私有作用域中私有变量name和age,这个和全局的没有半毛线关系
//varname="zhufeng";
//varage=6;
//})(name,age);//把全局变量name和age所存储的值传入到函数中,给函数的俩个形参变量
//函数执行。
//1.如果有形参,先给形参变量赋值
//2.然后在预解释
//然后在执行代码
varname="china";
varage=5000;
;(function(name,age){//是自执行函数的俩个形参变量
//私有作用域中私有变量name和age,这个和全局的没有半毛线关系
console.log("name+"+name+"age"+age);
})(name,age);
//通过window.属性名直接查找全局的
//这个是移动端Zepto.js实现的原理
varfn=(function(){
functionfn(){};
functionsum(){};
functiondd(){};
returnfn;
})();
//在真是项目当中,为了避免全局变量污染,静止使用全局变量(尤其是大公司)我们把要实现的功能用闭包的机制封装起来
;(function(){
functionfn(){