函数

搜狗:hanshu韩束  digui递归 jianjiediaoyong间接调用 lianshidiaoyong链式调用 arguments参数 return 返回值   gouzaohanshu构造函数   

 

 

 

要使用面向对象编程,不要面向过程编程。

对象:就是任意值的集合。

使用花括号表示: {  ...  }  如果没有值,那么就表示空对象

 

对象:任意值的集合

创建对象的方式一:字面量创建方式

//创建一个喵星人对象,花括号里面是他的属性(方法是属性的另一种别称),属性都是以键值对存在的,属性之间用逗号隔开

<script>
  var cat={ 
    "name":"zheng",
    "age":18,
    "family":["father","mother"],//属性可以是数组
    "speak":function(){//属性可以是函数
       console.log("喵喵!");
    }
    "friend":{//属性还可以是对象
      "name":"jerry",
      "age":19
    }
  };
</script>

--------

创建对象的方式二:构造函数创建法

var obj=new Object();

--------

创建对象的方式二:ECMAScript 5版本提供的创建方法(存在兼容性问题)

Object.create();

-------

对象属性的访问,修改,赋值,增加等操作

对上面喵星人对象增删改查

函数的定义, 普通函数 构造函数 本质 作为数据,递归, 链式调用,间接调用, arguments参数 return返回值
函数的定义:
//函数:一次申明,四次使用(调用)
//函数分为:命名函数(有函数名称的函数) 和 匿名函数(没有名称的函数)
//命名函数
function add(a,b){
//函数体,属于局部作用域
return a+b;// return 表示函数一死,可以烧纸,return后面的是函数返回值
console.log("return 后面的代码永远不会执行。");
};
add(3,8);
//匿名函数
window.onload=function(){
//函数体,属于局部作用域
alert("hellow");
};

//------函数执行过程-------
function add(a,b){
var result=a+b;
return result;
}
/*
-------上述函数每次被调用时都会发生的事情-------
1,浏览器全局对象window下面创建一个add方法
2,在add方法下面创建一个局部作用域
3,在局部作用域中创建变量 a=undefined , b=undefined , result=undefined
4,执行函数add(1,2);
5,给每个变量赋值 a=1 , b=2 , result=3
6,函数执行完毕,第一个要做的就是删除 add方法里面的局部作用域以及里面的变量,所以在外面无法访问里面的变量*/

//------------------------------------------
//------为什么要使用函数-------
/*1,复用代码
2,易于修改,维护
3,增加程序的可读性*/

//以下函数对可读性的优化
//下面代码每次看的话都要分析如何实现,怎么判断春夏秋冬,
//每次查看都要分析,细节暴露太多了,所以可读性不是很强。这里就需要封装函数了
function doThings(month){
if (month>=3 && month<=5) {
//踏春
}else if(month>=6 && month<=8){
//游泳
}else if(month>=9 && month<=11){
//秋收
}else{
//冬天睡觉
}
}
//什么时候可以使用函数?
//1,代码中有重复代码,或者有相似代码时,需要封装函数。
//2,功能实现时有很多代码,细节暴露太多,可读性很差时,就需要封装函数。
//
//把上面函数封装成可阅读性比较强,不暴露细节,直接读函数名称就可以知道做什么?
//在实现比较强的阅读性时,不要暴露具体实现的函数过程,直接一个函数名即可。
function isSpring(month){
return month>=3 && month<=5;
}
function isSummer(month){
return month>=6 && month<=8;
}
function isAutumn(month){
return month>=9 && month<=11;
}
function isWinter(month){
return month>12 && month<=2
}
function doThings(month){
if (isSpring()) {
//踏春
}else if(isSummer()){
//游泳
}else if(isAutumn()){
//秋收
}else{
//冬天睡觉
}
}
</script>
<script>
//-------------函数的本质---------------
/*函数二象性
1,函数可以调用
2,函数其实是对象:{}
定义对象的方式:
a,字面量的方式: var a={...}
b,构造函数的方式: var obj=new Object();
var arr=new Array();
添加属性和方法:
var person={};
person.name="zheng";
person.setName=function(name){
this.name=name;
}

var Person(arguments){
name:"zheng",
age:"18",
addredd:"China"
}
定义函数的方式:
a: function Person(arguments){...}
b: var fn = new Person(a,b,c);
*/
//-----以下是对象的操作-------
/*var a={
"name":"zheng",
"age":18,
"love":"you"
}
a.name="love";
a.setAge=function(age){
return a.age=age;
}
console.log(a.name);
console.log(a.setAge(88));
*/
//-----以下是函数的操作-------
function add(a,b){
age="zheng";
//设置age属性
return a+b
}
console.log(add.name);//返回 add,这里name是函数关键字 表示返回当前函数的函数名称
//给函数add设置age属性
add.setage=function(age){
this.age=age;
}
add.age="love";//重新设置 age 属性值
console.log(add.age);//返回 love
add.setage("you");//修改age的值
console.log(add.age);//返回 you
console.log(add(1,3));//输出 4
console.log(add);//输出add函数本体

//给add函数对象添加一个start函数
add.start=function(){
console.log("hello");
}
add.start();//执行start方法,输出hello
</script>

<script>
//---------函数作为数据值来使用----------
//值的集合是数组,键值对出现的就是对象
//值的集合是数组
var arr=[1,"a",function(){}];
for(var p in arr){
console.log(p);//输出的索引值 0 1 2
console.log(arr[p]);//arr[p] 输出的是arr中的对象
}
//键值对是对象
var array={"a":"love","b":"you","c":function(){}};
for(var p in array){
console.log(p);//输出array的属性
console.log(array[p]);//输出array的属性值
}

//---------函数作为参数来使用----------
//这里的函数作为参数使用
// setTimeout(function(){alert(1)},1000);//一秒钟后跳出弹窗
setTimeout(fn,1000);//函数名称表示函数本体,fn()表示立即执行该函数本体。
function fn(){
alert(1);
}

//---------函数作为返回值来使用----------
function add(){
return function(){alert(2)};
}
/*var newFn=add();//返回 return 后面的匿名函数本体
newFn();//函数本体后面添加小括号,表示立即执行该函数
*/
add();//得到 function(){alert(2)}; 这个返回值,是一个匿名函数本体。
add()();//表示执行匿名函数本体
</script>

//========函数的三种定义方式============
//-----第一,二种函数定义方式:------
字面量:
function声明:
function add(){...body...} //这里可以不要使用分号,这是函数
调用: add();

var赋值表达式:
var add=function(){...body...};//这里一定要使用分号,这是语句
调用: add();

var add=function fn(){...}
add(); //只能在外部调用,不能再函数体内调用
fn();//这么调用是错误的,fn属于局部变量,不可以在外面调用

//-----第三种函数定义方式:------
构造函数:
申明:var fn=new Function("a","b","return a+b;");
调用:fn();

//============函数定义的区别===============
字面量于构造函数的区别:
1,字面量定义:直观,简洁,方便书写
2,构造函数:笨重,复杂,效率低(解析字符串是变量是还函数体,实例化构造函数,函数体多的时候很难看)
构造函数的定义方式复杂难懂,效率较低,一般不用它来定义函数
使用构造函数的方式定义函数,不会被提前,函数调用必须在定义之后

声明方式:var声明方式 和 function声明方式 的区别:
1,使用var声明方式 是一个条语句,不会申明提前,所以最后要加分号;
2,使用function声明方式 是一个函数,会被申明提前,所以最后不要加分号。
3,预解析的过程的不同,如下代码:
<script>
//这里是预解析的时候已经定义了function add(),
//所以可以提前输出:function add(){return "a";}
//使用function声明的方式定义函数,声明会被提前,函数调用在定义前后都无所谓
console.log(add());//输出 a
function add(){
return "a";
}
//-----
console.log(add());
var add=function(){return "a";}
//预解析:
//var add=nudefined
//预解析完了再逐行执行代码。
//所以add是一个变量,不能当做函数执行add();
//-----
var ad=function(){return "b";}
console.log(ad());
//预解析:
//var ad=undefined;
//预解析完成,再重头开始逐行执行代码
//给 ad 进行赋值 ad=function(){return "b";}
//所以这里的 ad是一个函数 ad();
</script>

//使用时怎么选择函数
//构造函数 傻大黑粗效率低,一般不建议使用
//var 和 function 两种都差不多,一般都是根据团队风格进行选择的。
======================
<script>
//使用构造函数实现:21 * 32 + 24 / 3 - 5
var multiply=new Function("a","b", "return a*b;");//所有参数都必须使用字符串的形式,包括函数体。
// console.log(multiply("21","32"));//调用该方法时,只需要带参数即可,函数体不用写。
var divide=new Function("a","b","return a/b;");//所有参数都必须使用字符串的形式,包括函数体。
// console.log(divide("24","3"));//调用该方法时,只需要带参数即可,函数体不用写。
var substract=new Function("a","b","return a-b;");//所有参数都必须使用字符串的形式,包括函数体。
// console.log(substract("333","222"));//调用该方法时,只需要带参数即可,函数体不用写。

//等价下行:var add=new Function("a","b","return +a + +b;");//+a,+b表示取正,-a表示取负,!表示取反
var add=new Function("a","b","return parseInt(a)+parseInt(b);");//所有参数都必须使用字符串的形式,包括函数体。
// console.log(add("22","33"));//调用该方法时,只需要带参数即可,函数体不用写。
var mul=multiply("21","32");//返回:672
var divide=divide("24","3");//返回:8
var add=add(mul,divide);
console.log(add);//返回 680
var sub=substract(add,"5"); //返回 675
console.log(sub);//返回 675
</script>

//========函数定义的位置============
//具体哪里可以访问,请使用搜狗:zuoyongyu:作用域的知识
1,全局作用域
function add(){...} 在哪里都可以调用

2,函数作用域
//fn1()函数只能在substract函数中进行访问,不可以在全局中访问。
function substract(){
fn1();//可以访问
function fn1(){
fn1();//可以访问
function fn3(){
fn1();//可以访问
}
}
fn1();//可以访问
function fn2(){
fn1();//可以访问
}
}

3,不建议在代码块中定义函数:
在javascript中不存在 if/for代码块的作用域,里面的函数预解析为window全局作用域
if(true){
function add(argument){...}
}else{
function substract(argument){...}
}
//函数预解析时就提前声明了:
window下面的属性及其方法:
function add(argument){...}
function abstract(argument){...}
再逐行执行代码

------如果为真,就可以执行add()函数,否则就可以执行substract()函数-------
if(true){
var add=function(){...};
}else{
var substract=function(){...};
}
函数是在预解析之后再赋值的:
var add=undefined;
var substract=undefined;
再逐行执行代码
------
B:JS中没有块级作用域,所以不会在if中发生预解析,在外部预解析的时候,if中声明的所有函数都会被提前,所以无法达到按需定义的目的。
C:方法的调用必须指定对象,一般通过 对象.函数名() 的方式调用
D:内部函数可以访问外部函数的变量(作用域链的机制)
------

4,函数作为对象的属性值:
<script>
var person={
name:"zheng",
age:18,
address:"China",
setAddress:function(address){
this.address=address;
}
};
console.log(person.name);//输出:zheng
console.log(person.name="liang");//输出:liang
person.setName=function(name){this.name=name;}//添加设置修改姓名的方法
person.setName("zhu");//重新把name设置为:zhu
console.log(person.name);//输出:zhu
console.log(person.address);//输出:China
person.setAddress("American");//重新把address设置为:American
console.log(person.address);//输出:American
</script>
<script>
//如果输入两个数字类型,就相加,否则提示请输入数字类型的参数
var add=function(a,b){
if (isNumber(a) && isNumber(b)) {
return parseInt(a)+parseInt(b);//等价:return +a + +b; 一元运算符: +取正,-取负 !取反
}else{
return "请输入数字类型的参数";
}
}
function isNumber(a){
return isNaN(a)?false:true;//如果isNaN(a)=true,那么返回false ,否则返回true
}
console.log(add("333","bbb"));
console.log("33","22");
</script>

//------函数的调用------
<script>
//命名函数的调用
function add(a,b){
return a*b;
}
add();//命名函数的调用

//匿名函数的调用
//1,使用 变量名+() 进行调用
var add=function(a,b){
return a*b;
}
add();//

//2,匿名函数自我执行
/*function(){console.log(1);}();
在预解析时:function后面一定要跟上一个函数名称,
但这里没有函数名称,所以会报错。解决办法如下:*/

//匿名函数自执行方法一:
//把匿名函数自我执行后的结果赋值给变量a即可,函数名称+()表示立即执行函数本体。
/*var a =function(a,b){return 3*4}();
console.log(a);

//匿名函数自执行方法二,三效果一模一样
//匿名函数自执行方法二:
(function(){console.log(2)}());
//匿名函数自执行方法三:
(function(){console.log(3)})()
//匿名函数自执行方法四:
//!表示取反,+表示取正,-表示取负数,只要不让匿名函数的function打头,那就可以匿名函数自执行
!function(){console.log(4)}();
+function(){console.log(4)}();
-function(){console.log(4)}();
!+~-function(){console.log(4)}();
//匿名函数自执行方法五:
console.log(function(){return 5;}());*/

<script>
(function(){
function add(a,b){
return a+b;
}
console.log(add(1,3));//而这里返回的4
})();
console.log(add(1,3));//这里调用报错,因为add函数是在匿名函数的作用域内,不可以当做全局变量来使用
</script>

//------递归函数------
5的阶乘:5*4*3*2*1
//递归函数,类似于循环
//1,一定有一个终结点退出函数执行
//2,同理一直进行自我调用
<script>
function factorial(num){
if (num<=1) return 1;
return num*factorial(num-1);
}
console.log(factorial(5));

//上面的递归等同于下面的函数:
/*5*4*3*2*1
5!
5*4!
5*4*3!*/
var sum=1;
function a(num){
var i=1;
while (i<=num) {
sum=sum*i;
i++;
}
return sum;
}
console.log(a(5));
</script>

<script>
//求阶乘,这里没有终止条件,值域溢出,所以死循环
function factorial(num){
return num*factorial(num-1);
}
factorial(5);
</script>

<!-- 对象调用方法 -->
<script>
var operation={
//加法
add:function(a,b){
return a+b;
},
//减法
substract:function(a,b){
return a-b;
},
//乘法
multiply:function(a,b){
return a*b;
},
//除法
divide:function(a,b){
return a/b;
},
//使用不合法的字符串时,只能使用:对象["@"]()运行函数
"@":function(){
console.log("999");
alert("1");
}
}
//使用合法字符串命名,可以使用以下两种方法进行调用函数
console.log(operation["add"](3,6));
console.log(operation.add(3,6));
//使用不合法的字符串时,只能使用: 对象["@"]() 运行函数
operation["@"]();

var key="add";
// []方括号中,有双引号的表示字符串,没有双引号的表示变量,谨记
console.log(operation[key](1,3));//返回:4 这里的是变量:key="add"
console.log(operation["key"]());// 返回:key 这里的key是对象operation中的方法。

//-------链式调用方法-------
// $("p").html("love you forever").css("backgrond","red")...
var operation={
//加法
add:function(a,b){
console.log(a+b);
return this;//返回的是operation对象
},
//减法
substract:function(a,b){
console.log(a-b);
return this;//返回的是operation对象
}
}
// operation.add(2,3); 返回的是 operation 对象
// operation.substract; 返回的是 operation 对象
//所以可以使用下面的链式调用,否则是不可以的。
operation.add(2,3).substract(33,3);
</script>
<script>
//这是需要鼠标点击才可以调用点击方法
document.onclick=function(){
alert("1");
}
//不用点击直接调用方法,任意方法直接在方法名称后面添加 (),就会立马执行该方法
document.onclick();
</script>
<script>
//什么是构造函数
//普通函数有return 则返回 return后面的值,如果没有return,则返回undefined
//函数名称小写用于区分:普通函数,不是严格规定
//函数名称大写的用于区分:构造函数,不是严格规定
function add(a,b){return a+b;}
//普通函数的调用:函数名称()
add(3,4);

// function Person(){...}
//new Person() 用于实例化构造函数
// var Obj=new Person();
//Person();这么调用就是普通函数
//Array();这是普通函数
//Object();这是普通函数
console.log(Array());//返回 []
console.log(Object());//返回 {}
var arr=new Array();//实例化一个数组 返回的永远是对象
var obj=new Object();//实例化一个对象 返回的永远是对象

////-------实例化一个Person--------
/////构造函数,顾名思义:被构造的对象也必须是一个函数。
function Person(){
this.name="zheng";//这里一定要使用this.属性,否则后面输出都是undefined.
this.age=18;//这里一定要使用this.属性,否则后面输出都是undefined.
var address="China";//实例化后,输出为undefined
}
var xm=new Person();//实例化一个Person对象
console.log(xm);//Person {name: "zheng", age: 18} address定义错误不是属性
console.log(xm.name);//输出 zheng
console.log(xm.age);//输出 18
console.log(xm.address);//输出 undefined
</script>

<script>
//创建一个空的Person对象
var Person=function(){};
//实例化Person对象
var per=new Person();
//给对象添加属性
per.name="zheng";
per.age="18";
per.sex="male";
//实例化一个数组
var arr=new Array();
//给数组arr添加属性
arr[0]="zheng";
arr[1]="liang";
//遍历per对象并输出属性及其属性值
for(var p in per){
console.log(p+":"+per[p]);
}
//遍历数组arr并输出值
for (var i = 0; i < arr.length; i++) {
console.log(arr[i]);
}
</script>
<script>
//------间接调用--------
var name="xm";
var person={};
person.name="xh";
person.getName=function(){
return this.name;
}
console.log(person.getName());//输出:xh
//这里的window用于改变person.getName里面的this变成:window,即返回window.name的值
console.log(person.getName.call(window));//输出:xm
//这里的window用于改变person.getName里面的this变成:window,即返回window.name的值
console.log(person.getName.apply(window));//输出:xm

var arr=[2,5];
function add(a,b){
return a+b;
}
//直接调用
console.log(add(3,6));
//使用了间接调用,call(指定作用域对象,argument1,argumen2...)
console.log(add.call(window,2,5));
//这里间接调用了window下面的arr的数组值, apply(指定作用域对象,数组)
console.log(add.apply(window,arr));
//间接调用:
//1,对象没有call和apply方法,只有函数有
//2,apply可以将数组和类数组一次性的传递进函数中,call只能一个一个的传
</script>
//------arguments 参数------
//参数分为:实参,形参
1,当参数为基本数据类型时,只是进行了复制操作,不不会修改原来的值。
2,当参数为引用类型时,因为两个引用地址相同,指向同一个值。如果修改其中一个,另一个也会被修改。
//三种情况:
1,实参=形参
<script>
//函数中的参数:形式参数 实际参数
function add(a,b){//这里的 a,b是形式参数,占位符的作用
return a+b;
}
add(3,8);//这里的3 ,8 是实际参数
//本质上就是复制一个副本: 形参=实参 ,对于原来的值是不改变的。
// var a=3; var b=8;

//参数为对象时,参数为引用类型,那么传递的是地址。修改一个同时也会修改另一个
var person={};
var setName=function(obj){//这里的参数是对象,给指定对象设置name属性
obj.name="zheng";
}
setName(person);//这里的person是对象,给person对象设置name属性
console.log(person.name);
</script>

2,实参<形参
<script>
//求数的幂 Math.pow(base,power);
function pow(base,power){
return Math.pow(base,power);
}
console.log(pow(3,4));//返回 81
console.log(pow(3,2));//返回 9

function pow(base,power){
// if (!power) power=2;//如果b为空:!power=true,如果b不存在为真的,那么返回b=2.
//短路操作
power=power || 2;//或逻辑 一个为真即为真 如果power=power返回true,那么power=power,否则b=2;
return Math.pow(base,power);
}
console.log(pow(4));//返回 16
console.log(pow(3));//返回 9

//$("p");//默认省略document
//在JQuery中的参数: $("p",document):表示在文档中查找P标签。
//也可指定某个对象:$("p",document.getElementById("box")),
//指定id="box"的对象下面查找p标签。
</script>

3,实参>形参
<script>
function add(){
//任何函数都有返回值,返回return后面的值,如果省略return或者return后面没有值,则返回undefined
if (arguments.length==0) return;
var sum=0;
for (var i = 0; i < arguments.length; i++) {
sum+=arguments[i];
}
return sum;
}
console.log(add()); // 返回 undefined
console.log(add(1,3,4));//返回 8
</script>
<script>
// 输入任意个数字参数,输出最小值
function mix(){
var len=arguments.length;
if (len==0) return;
if (len==1) return arguments[0];
var mi=0;
for (var i = 1; i < len; i++) {
//思路决定出路
// 这里是精华所在,前后对比,把较小的一个赋值给arguments[i]
arguments[i]= arguments[i-1]<arguments[i]?arguments[i-1]:arguments[i];
mi = arguments[i];
}
return mi;
}
console.log(mix(1,3,444,2,5245,7373,2452,-11,-23432,-234,-245));
console.log(mix());
console.log(mix(888))
</script>

//arguments
//参数是每个函数都有的,是一个局部变量
//类数组对象,但不是数组的实例。可以使用arguments[index]进行取值.
<script>
//合法标识符:不能以数字,关键字,保留字开头,以字母,数字,下划线组成的字符串;
//这里arguments的索引是 "0" 到 "5" ,数字是不合法的标识符,所以只能使用双引号。
//以下就是类数组对象:
var arguments={
"0":"argument1",
"1":"argument2",
"2":"argument3",
"3":"argument4",
"4":"argument5",
"5":"argument6"
};
//遍历arguments类数组对象
for(var p in arguments){
console.log(p+":"+arguments[p]);
}

//1.对象的长度不能用.length获取,用js原生的Object.keys可以获取到
console.log(arguments.length);//返回 undefined
var keys=Object.keys(arguments)//使用原生Object.keys,获取键值对中键的集合,都是数组
var values=Object.values(arguments)//使用原生Object.values,获取键值对中值的集合,都是数组
console.log(keys.length);//两种都可以获得对象的长度
console.log(values.length);//两种都可以获得对象的长度
//但是,如果arguments作为函数中的参数,是可以通过arguments.length获得实际参数个数。
//函数是一个特殊对象,也可以通过add.length 获得形式参数个数
<script>
function add(a,b,c){
console.log(arguments.length);//返回 5 调用函数是写入的实际参数
console.log(add.length);//返回 3,定函数时,定义的形式参数
console.log(arguments.callee.length);//返回 3 形式参数,函数固定的形式参数长度
return +a + +b + +c;//一元运算符,+取正,-取负,!取反
}
// console.log(add(1,3,5));
console.log(add(1,3,6,7,8));//返回:10 只对前面3个参数进行相加

</script>
//------
function fn(arguments){
console.log(argument);
function fn1(arguments){
console.log(argument);
}
fn1(2);//输出2
}
fn(1);//输出1
//arguments是每个函数中独有的,不同作用域不同
//预解析:
/*fn函数作用域:
var argument=undefined;
fn1函数作用:
var argument=undefined;
*/
</script>
//--------
// "use strict" //表示使用严格模式
// var num=1;//这样定义num变正确
// num=1;//这样定义num变就会报错
</script>
<script>
//判断传入参数是否等于实际参数
function add(a,b){
//console.log(arguments.length);//返回 5实际参数,我们实际传入的参数
//console.log(arguments.callee.length);//返回 2 形式参数,函数固定的形式参数
// console.log(add.length);返回 2 //形式参数,函数固定的形式参数,可以在函数外面进行调用
if (arguments.length!==add.length) throw new Error("请输入:"+add.length+"个参数");
return a+b;
}
// console.log(add(2,4));//返回 6
console.log(add(1,3,4,5,6));//参数不对,参数过多。返回:text2.html:13 Uncaught Error: 请输入:2个参数
</script>
//---------------
<body>
<p id="test" style="background-color: red; color: blue;">我是一个段落!</p>
<script type="text/javascript">
//在使用参数给对象设置CSS属性时,都是用p.style[property]=value,这样绝对没错
//如果使用p.style.property=value。读取时使用,设置时有可能会报错。
var p=document.getElementById('test');
function css(value,property){//必要参数一定要放在第一个,可传可不传放在后面
if (arguments.length<=0 || arguments.length>=3) throw new Error("请输入:"+arguments.length+"参数");
if (property==undefined) p.style.backgroundColor=value;
if (arguments.length==2) p.style[property]=value;
}
css("orange");//第二个参数省略,默认 property=undefined
// css("green","backgroundColor");
</script>
</body>
<script type="text/javascript">
//-----什么可以当做变量-------
//1,什么都不传
var a=2;
function fn(){
function(){alert(a);}
}
//2,数字
function fn(num){console.log(num);}
fn(2);
//3,字符串
//4,boolean
function a(){}
function b(){}
//如果传进来的是布尔值,一定使用要把细节封装成a,b函数。经验之谈。
function fn(boolean){
if (true) {
a();
}else{
b();
}
}
//5,undefined
function add(a,b){
if (b==undefined) return a;
return a+b;
}
console.log(add(6,undefined));//返回 NaN,非数字
function pow(bace,power){
//短路操作,如果power=power=true则power=power power=undefined=false 则power=2。
power=power || 2;
return Math.pow(bace,power);
}
console.log(pow(3,6));
//6,null
//以上都是单个参数传递
//
//7,传多个参数,如数组:[1,2,3,4,5]
$.each([1,2,3,4,5], function(index, val) {
console.log(index);
console.log(val);
});
for (var i = 0; i < [1,2,3,4,5].length; i++) {
console.log(index);
console.log(val);
}
//8,传对象:{"a":"1","b":"2","c":"3"}
$.each({"a":"1","b":"2","c":"3"}, function(index, val) {
console.log(index);
console.log(val);
});

//下面代码使用对象作为参数进行代码优化:
function setPerson(name,sex,age,add,phone){
var person={};
person.name=name;
person.sex=sex;
person.age=age;
person.add=add;
person.phone=phone;
}
//可读性,可写性不强,很容易弄错参数顺序导致错误,所以下面可以使用对象代替
setPerson("zhengl","male",18,"中国China","182...");

//当参数超过三个或者三个以上,建议适用对象进行代码优化如下:
var person={};
function setPerson(obj){
person.name=obj.name || "xh";//如果没有设置该属性,则设置一个默认值
person.age=obj.age || 18;//如果没有设置该属性,则设置一个默认值
person.add=obj.add || "中国China";//如果没有设置该属性,则设置一个默认值
person.sex=obj.sex || "male";//如果没有设置该属性,则设置一个默认值
person.phone=obj.phone || "110";//如果没有设置该属性,则设置一个默认值
}
//经过代码优化:对象属性不用按顺序进行书写,甚至不写都不会报错。
setPerson({
name:"zheng",
age:18,
sex:"male"
// add:"中国China", 两个属性值没写,使用默认值
// phone:"187" 两个属性值没写,使用默认值
});
console.log(person.age);
console.log(person.add);
console.log(person.phone);

//9,函数作为参数,就叫回调函数
$.each(obj,function(){...})
setInterval(function(){},1000)
</script>
<script type="text/javascript">
/*
//--------返回值:--------
return
1,表示 函数的结束。
2,表示 返回return 后面的值。如果后面没有值,则返回undefined

return 表示在函数中使用,函数返回一个值。

continue 用于循环,表示跳出本次循环,执行下一次循环

break 跳出整个循环,执行循环以外的代码*/

//1,没有返回值: 默认undefined
function fn(){}
function fn1 () {
return;//表示返回值为undefined
}
function fn2(a,b){
if (b<0) return;//表示函数结束执行
return a/b;//表示返回值
}
console.log(fn());//返回 undefined
console.log(fn1());//返回 undefined
//2,数字做返回值
//3,字符串作为返回值
alert(1,2,3,4);返回字符串:1,2,3
alert([1,2,3,4]);//返回字符串:1,2,3 默认会隐式转换:[1,2,3,4].toString();
alert([1,2,3,4].toString());返回字符串:1,2,3
//4,boolea return true/false
//5,null
//6,数组 返回多个值
function fn(a,b){return [a+b,a,b];}
//7,对象
function getPerson(){
return {//不用创建对象了,直接返回一个对象即可
name:"zheng",
age:18
};
}
console.log(getPerson());//{name: "zheng", age: 18}

//一下代码风格要小心,return在解析时,系统会自动给return添加分号;,从而报错。
/*function getPerson()
{
return //return在解析时,系统会自动给return添加分号;,从而报错。
{
name:"zheng",
age:18
};
}
console.log(getPerson());//{name: "zheng", age: 18}*/
//8,函数
function fn(){
return function (){
console.log("one");
}
}
// 返回:
// ƒ fn(){
// return function (){
// console.log("one");
// }
// }
console.log(fn);
//返回:ƒ (){ console.log("one"); }
console.log(fn());
//返回:one
console.log(fn()());
//------
document.write([1,3,5]);//返回 1,3,5 进行了隐式转换[1,3,5].toString();
document.write({"name":"zheng","age":18,toString:function(){
document.write("love");
}});//返回:[object Object]
console.log({"name":"zheng","age":18,function(){
document.write("love");
}});//返回:{name: "zheng", age: 18, function: ƒ}

/*为了写出更优雅的函数,会将函数作为参数传递到另一个函数中,组成一个新功能的函数:
两个功能:
1,传进来函数的功能。
2,接收函数的功能。
一个函数实现一个功能,把多个函数组合成一个新的函数,就实现了一个复合的功能。*/
</script>
//------关于局部作用域,调用一次就创建一次,也删除一次-------
<script type="text/javascript">
function count(){
var num=1;
return function(){
return num++;//先返回 num,再num+1
// return ++num;//先num+1,再返回 num
}
}
console.log(count()());//每次调用普通函数,都会创建一个新的局部作用域,函数执行完连被删除
console.log(count()());//每次调用普通函数,都会创建一个新的局部作用域,函数执行完连被删除
console.log(count()());//每次调用普通函数,都会创建一个新的局部作用域,函数执行完连被删除
var fn=count();//这里只调用一次函数,只开辟一个局部作用域,所以里面的num执行几次就会加1几次。
console.log(fn());//fn()=count()();
console.log(fn());//fn()=count()();
console.log(fn());//fn()=count()();
//返回:1 ,1 ,1 ,1 ,2 ,3

// 1、 count()()这样调用,每次都会创建一个新的局部作用域,num的值会不断地被初始化为1

// 2、 return num++表示先返回num的值,再将num加1

// 3、 先将count()赋给fn,此时count()只调用了一次,接下来多次调用fn()的时候,count函数并没有多次调用,num只会在count函数调用的时候被初始化,所以多次调用fn()的时候num不会被多次初始化;由于fn相当于count函数的内层函数(var fn=count();这行代码执行后,就调用了count(),调用count后就将里面的函数赋值给了fn,所以说fn就相当于函数的内层函数了。),可以访问count中的变量num,所以多次调用fn函数,会将num的值累加;
</script>

 

函数的定义, 普通函数 构造函数 本质 作为数据,递归, 链式调用,间接调用,  arguments参数 return返回值函数的定义:   //函数:一次申明,四次使用(调用)   //函数分为:命名函数(有函数名称的函数) 和 匿名函数(没有名称的函数)   //命名函数   function add(a,b){   //函数体,属于局部作用域   return a+b;// return 表示函数一死,可以烧纸,return后面的是函数返回值   console.log("return 后面的代码永远不会执行。");   };   add(3,8);   //匿名函数    window.onload=function(){   //函数体,属于局部作用域   alert("hellow");   };
   //------函数执行过程-------   function add(a,b){   var result=a+b;   return result;   }   /*   -------上述函数每次被调用时都会发生的事情-------   1,浏览器全局对象window下面创建一个add方法   2,在add方法下面创建一个局部作用域   3,在局部作用域中创建变量 a=undefined , b=undefined , result=undefined   4,执行函数add(1,2);   5,给每个变量赋值 a=1 , b=2 , result=3   6,函数执行完毕,第一个要做的就是删除 add方法里面的局部作用域以及里面的变量,所以在外面无法访问里面的变量*/
//------------------------------------------   //------为什么要使用函数-------   /*1,复用代码   2,易于修改,维护   3,增加程序的可读性*/
   //以下函数对可读性的优化   //下面代码每次看的话都要分析如何实现,怎么判断春夏秋冬,   //每次查看都要分析,细节暴露太多了,所以可读性不是很强。这里就需要封装函数了   function doThings(month){   if (month>=3 && month<=5) {   //踏春   }else if(month>=6 && month<=8){   //游泳   }else if(month>=9 && month<=11){   //秋收   }else{   //冬天睡觉   }   }   //什么时候可以使用函数?   //1,代码中有重复代码,或者有相似代码时,需要封装函数。   //2,功能实现时有很多代码,细节暴露太多,可读性很差时,就需要封装函数。   //   //把上面函数封装成可阅读性比较强,不暴露细节,直接读函数名称就可以知道做什么?   //在实现比较强的阅读性时,不要暴露具体实现的函数过程,直接一个函数名即可。   function isSpring(month){     return month>=3 && month<=5;   }   function isSummer(month){     return month>=6 && month<=8;   }   function isAutumn(month){     return month>=9 && month<=11;   }   function isWinter(month){     return month>12 && month<=2   }   function doThings(month){      if (isSpring()) {      //踏春      }else if(isSummer()){      //游泳      }else if(isAutumn()){      //秋收      }else{      //冬天睡觉      }   }</script><script>//-------------函数的本质---------------/*函数二象性1,函数可以调用2,函数其实是对象:{}定义对象的方式:a,字面量的方式: var a={...}b,构造函数的方式: var obj=new Object();var arr=new Array();添加属性和方法:var person={};person.name="zheng";person.setName=function(name){this.name=name;}
var Person(arguments){name:"zheng",age:"18",addredd:"China"}定义函数的方式:a: function Person(arguments){...}b: var fn = new Person(a,b,c);*///-----以下是对象的操作-------/*var a={"name":"zheng","age":18,"love":"you"}a.name="love";a.setAge=function(age){return a.age=age;}console.log(a.name);console.log(a.setAge(88));*///-----以下是函数的操作-------function add(a,b){age="zheng";//设置age属性return a+b}console.log(add.name);//返回 add,这里name是函数关键字 表示返回当前函数的函数名称//给函数add设置age属性add.setage=function(age){this.age=age;}add.age="love";//重新设置 age 属性值console.log(add.age);//返回 loveadd.setage("you");//修改age的值console.log(add.age);//返回 youconsole.log(add(1,3));//输出 4console.log(add);//输出add函数本体
//给add函数对象添加一个start函数add.start=function(){console.log("hello");}add.start();//执行start方法,输出hello</script>
<script>//---------函数作为数据值来使用----------//值的集合是数组,键值对出现的就是对象//值的集合是数组var arr=[1,"a",function(){}];for(var p in arr){console.log(p);//输出的索引值 0 1 2console.log(arr[p]);//arr[p] 输出的是arr中的对象}//键值对是对象var array={"a":"love","b":"you","c":function(){}};for(var p in array){console.log(p);//输出array的属性console.log(array[p]);//输出array的属性值}
//---------函数作为参数来使用----------//这里的函数作为参数使用// setTimeout(function(){alert(1)},1000);//一秒钟后跳出弹窗setTimeout(fn,1000);//函数名称表示函数本体,fn()表示立即执行该函数本体。function fn(){alert(1);}
//---------函数作为返回值来使用----------function add(){return function(){alert(2)};}/*var newFn=add();//返回 return 后面的匿名函数本体newFn();//函数本体后面添加小括号,表示立即执行该函数*/add();//得到 function(){alert(2)}; 这个返回值,是一个匿名函数本体。add()();//表示执行匿名函数本体</script>
//========函数的三种定义方式============//-----第一,二种函数定义方式:------字面量:   function声明:  function add(){...body...}  //这里可以不要使用分号,这是函数调用: add();
var赋值表达式:var add=function(){...body...};//这里一定要使用分号,这是语句调用: add();
var add=function fn(){...}add(); //只能在外部调用,不能再函数体内调用fn();//这么调用是错误的,fn属于局部变量,不可以在外面调用//-----第三种函数定义方式:------构造函数:申明:var fn=new Function("a","b","return a+b;");调用:fn();
//============函数定义的区别===============字面量于构造函数的区别:1,字面量定义:直观,简洁,方便书写2,构造函数:笨重,复杂,效率低(解析字符串是变量是还函数体,实例化构造函数,函数体多的时候很难看)        构造函数的定义方式复杂难懂,效率较低,一般不用它来定义函数         使用构造函数的方式定义函数,不会被提前,函数调用必须在定义之后
声明方式:var声明方式 和 function声明方式 的区别:1,使用var声明方式 是一个条语句,不会申明提前,所以最后要加分号;2,使用function声明方式 是一个函数,会被申明提前,所以最后不要加分号。3,预解析的过程的不同,如下代码:<script>//这里是预解析的时候已经定义了function add(),//所以可以提前输出:function add(){return "a";}//使用function声明的方式定义函数,声明会被提前,函数调用在定义前后都无所谓console.log(add());//输出 afunction add(){return "a";}//-----console.log(add());var add=function(){return "a";}//预解析://var add=nudefined//预解析完了再逐行执行代码。//所以add是一个变量,不能当做函数执行add();//-----var ad=function(){return "b";}console.log(ad());//预解析://var ad=undefined;//预解析完成,再重头开始逐行执行代码//给 ad 进行赋值 ad=function(){return "b";}//所以这里的 ad是一个函数 ad();</script>
//使用时怎么选择函数//构造函数 傻大黑粗效率低,一般不建议使用//var 和 function 两种都差不多,一般都是根据团队风格进行选择的。======================<script>//使用构造函数实现:21 * 32 + 24 / 3 - 5var multiply=new Function("a","b", "return a*b;");//所有参数都必须使用字符串的形式,包括函数体。// console.log(multiply("21","32"));//调用该方法时,只需要带参数即可,函数体不用写。var divide=new Function("a","b","return a/b;");//所有参数都必须使用字符串的形式,包括函数体。// console.log(divide("24","3"));//调用该方法时,只需要带参数即可,函数体不用写。var substract=new Function("a","b","return a-b;");//所有参数都必须使用字符串的形式,包括函数体。// console.log(substract("333","222"));//调用该方法时,只需要带参数即可,函数体不用写。//等价下行:var add=new Function("a","b","return +a + +b;");//+a,+b表示取正,-a表示取负,!表示取反var add=new Function("a","b","return parseInt(a)+parseInt(b);");//所有参数都必须使用字符串的形式,包括函数体。// console.log(add("22","33"));//调用该方法时,只需要带参数即可,函数体不用写。var mul=multiply("21","32");//返回:672var divide=divide("24","3");//返回:8var add=add(mul,divide);console.log(add);//返回 680var sub=substract(add,"5"); //返回 675console.log(sub);//返回 675</script>
//========函数定义的位置============//具体哪里可以访问,请使用搜狗:zuoyongyu:作用域的知识1,全局作用域function add(){...} 在哪里都可以调用
2,函数作用域//fn1()函数只能在substract函数中进行访问,不可以在全局中访问。function substract(){fn1();//可以访问function fn1(){fn1();//可以访问function fn3(){fn1();//可以访问}}fn1();//可以访问function fn2(){fn1();//可以访问}}
3,不建议在代码块中定义函数:在javascript中不存在 if/for代码块的作用域,里面的函数预解析为window全局作用域if(true){function add(argument){...}}else{function substract(argument){...}}//函数预解析时就提前声明了:window下面的属性及其方法:function add(argument){...}function abstract(argument){...}再逐行执行代码
------如果为真,就可以执行add()函数,否则就可以执行substract()函数-------if(true){var add=function(){...};}else{var substract=function(){...};}函数是在预解析之后再赋值的:var add=undefined;var substract=undefined;再逐行执行代码------B:JS中没有块级作用域,所以不会在if中发生预解析,在外部预解析的时候,if中声明的所有函数都会被提前,所以无法达到按需定义的目的。C:方法的调用必须指定对象,一般通过 对象.函数名() 的方式调用D:内部函数可以访问外部函数的变量(作用域链的机制)------
4,函数作为对象的属性值:<script>var person={name:"zheng",age:18,address:"China",setAddress:function(address){this.address=address;}};console.log(person.name);//输出:zhengconsole.log(person.name="liang");//输出:liangperson.setName=function(name){this.name=name;}//添加设置修改姓名的方法person.setName("zhu");//重新把name设置为:zhuconsole.log(person.name);//输出:zhuconsole.log(person.address);//输出:Chinaperson.setAddress("American");//重新把address设置为:Americanconsole.log(person.address);//输出:American</script><script>//如果输入两个数字类型,就相加,否则提示请输入数字类型的参数var add=function(a,b){if (isNumber(a) && isNumber(b)) {return parseInt(a)+parseInt(b);//等价:return +a + +b; 一元运算符: +取正,-取负 !取反}else{return "请输入数字类型的参数";}}function isNumber(a){return isNaN(a)?false:true;//如果isNaN(a)=true,那么返回false ,否则返回true}console.log(add("333","bbb"));console.log("33","22");</script>
//------函数的调用------<script>//命名函数的调用function add(a,b){return a*b;}add();//命名函数的调用
//匿名函数的调用//1,使用 变量名+() 进行调用var add=function(a,b){return a*b;}add();//
//2,匿名函数自我执行/*function(){console.log(1);}();在预解析时:function后面一定要跟上一个函数名称,但这里没有函数名称,所以会报错。解决办法如下:*///匿名函数自执行方法一://把匿名函数自我执行后的结果赋值给变量a即可,函数名称+()表示立即执行函数本体。/*var a =function(a,b){return 3*4}();console.log(a);
//匿名函数自执行方法二,三效果一模一样//匿名函数自执行方法二:(function(){console.log(2)}());//匿名函数自执行方法三:(function(){console.log(3)})()//匿名函数自执行方法四://!表示取反,+表示取正,-表示取负数,只要不让匿名函数的function打头,那就可以匿名函数自执行!function(){console.log(4)}();+function(){console.log(4)}();-function(){console.log(4)}();!+~-function(){console.log(4)}();//匿名函数自执行方法五:console.log(function(){return 5;}());*/
<script>(function(){function add(a,b){return a+b;}console.log(add(1,3));//而这里返回的4})();console.log(add(1,3));//这里调用报错,因为add函数是在匿名函数的作用域内,不可以当做全局变量来使用</script>
//------递归函数------5的阶乘:5*4*3*2*1//递归函数,类似于循环//1,一定有一个终结点退出函数执行//2,同理一直进行自我调用<script>function factorial(num){if (num<=1) return 1;return num*factorial(num-1);}console.log(factorial(5));
//上面的递归等同于下面的函数:/*5*4*3*2*15!5*4!5*4*3!*/var sum=1;function a(num){var i=1;while (i<=num) {sum=sum*i;i++;}return sum;}console.log(a(5));</script>
<script>//求阶乘,这里没有终止条件,值域溢出,所以死循环function factorial(num){return num*factorial(num-1);}factorial(5);</script>
<!-- 对象调用方法 --><script>var operation={//加法add:function(a,b){return a+b;},//减法substract:function(a,b){return a-b;},//乘法multiply:function(a,b){return a*b;},//除法divide:function(a,b){return a/b;},//使用不合法的字符串时,只能使用:对象["@"]()运行函数"@":function(){console.log("999");alert("1");}}//使用合法字符串命名,可以使用以下两种方法进行调用函数console.log(operation["add"](3,6));console.log(operation.add(3,6));//使用不合法的字符串时,只能使用: 对象["@"]() 运行函数operation["@"]();
var key="add";// []方括号中,有双引号的表示字符串,没有双引号的表示变量,谨记console.log(operation[key](1,3));//返回:4  这里的是变量:key="add"console.log(operation["key"]());// 返回:key  这里的key是对象operation中的方法。
//-------链式调用方法-------// $("p").html("love you forever").css("backgrond","red")...var operation={//加法add:function(a,b){console.log(a+b);return this;//返回的是operation对象},//减法substract:function(a,b){console.log(a-b);return this;//返回的是operation对象}}// operation.add(2,3); 返回的是 operation 对象// operation.substract; 返回的是 operation 对象//所以可以使用下面的链式调用,否则是不可以的。operation.add(2,3).substract(33,3);</script><script>//这是需要鼠标点击才可以调用点击方法document.onclick=function(){alert("1");}//不用点击直接调用方法,任意方法直接在方法名称后面添加 (),就会立马执行该方法document.onclick();</script><script>//什么是构造函数//普通函数有return 则返回 return后面的值,如果没有return,则返回undefined//函数名称小写用于区分:普通函数,不是严格规定//函数名称大写的用于区分:构造函数,不是严格规定 function add(a,b){return a+b;}//普通函数的调用:函数名称()add(3,4);// function Person(){...}//new Person() 用于实例化构造函数// var Obj=new Person();//Person();这么调用就是普通函数//Array();这是普通函数//Object();这是普通函数console.log(Array());//返回 []console.log(Object());//返回 {}var arr=new Array();//实例化一个数组 返回的永远是对象var obj=new Object();//实例化一个对象 返回的永远是对象
////-------实例化一个Person--------/////构造函数,顾名思义:被构造的对象也必须是一个函数。function Person(){this.name="zheng";//这里一定要使用this.属性,否则后面输出都是undefined.this.age=18;//这里一定要使用this.属性,否则后面输出都是undefined.var address="China";//实例化后,输出为undefined}var xm=new Person();//实例化一个Person对象console.log(xm);//Person {name: "zheng", age: 18} address定义错误不是属性console.log(xm.name);//输出 zhengconsole.log(xm.age);//输出 18console.log(xm.address);//输出 undefined</script>
<script>//创建一个空的Person对象var Person=function(){};//实例化Person对象var per=new Person();//给对象添加属性per.name="zheng";per.age="18";per.sex="male";//实例化一个数组var arr=new Array();//给数组arr添加属性arr[0]="zheng";arr[1]="liang";//遍历per对象并输出属性及其属性值for(var p in per){console.log(p+":"+per[p]);}//遍历数组arr并输出值for (var i = 0; i < arr.length; i++) {console.log(arr[i]);}</script><script>//------间接调用--------var name="xm";var person={};person.name="xh";person.getName=function(){return this.name;}console.log(person.getName());//输出:xh//这里的window用于改变person.getName里面的this变成:window,即返回window.name的值console.log(person.getName.call(window));//输出:xm//这里的window用于改变person.getName里面的this变成:window,即返回window.name的值console.log(person.getName.apply(window));//输出:xm
var arr=[2,5];function add(a,b){return a+b;}//直接调用console.log(add(3,6));//使用了间接调用,call(指定作用域对象,argument1,argumen2...)console.log(add.call(window,2,5));//这里间接调用了window下面的arr的数组值, apply(指定作用域对象,数组)console.log(add.apply(window,arr));//间接调用://1,对象没有call和apply方法,只有函数有//2,apply可以将数组和类数组一次性的传递进函数中,call只能一个一个的传</script>//------arguments 参数------//参数分为:实参,形参1,当参数为基本数据类型时,只是进行了复制操作,不不会修改原来的值。2,当参数为引用类型时,因为两个引用地址相同,指向同一个值。如果修改其中一个,另一个也会被修改。//三种情况:1,实参=形参<script>//函数中的参数:形式参数 实际参数function add(a,b){//这里的 a,b是形式参数,占位符的作用return a+b;}add(3,8);//这里的3 ,8 是实际参数//本质上就是复制一个副本:  形参=实参 ,对于原来的值是不改变的。// var a=3;  var b=8;
//参数为对象时,参数为引用类型,那么传递的是地址。修改一个同时也会修改另一个var person={};var setName=function(obj){//这里的参数是对象,给指定对象设置name属性obj.name="zheng";}setName(person);//这里的person是对象,给person对象设置name属性console.log(person.name);</script>
2,实参<形参<script>//求数的幂  Math.pow(base,power);function pow(base,power){return Math.pow(base,power);}console.log(pow(3,4));//返回 81console.log(pow(3,2));//返回 9
function pow(base,power){// if (!power) power=2;//如果b为空:!power=true,如果b不存在为真的,那么返回b=2.//短路操作power=power || 2;//或逻辑 一个为真即为真 如果power=power返回true,那么power=power,否则b=2;return Math.pow(base,power);}console.log(pow(4));//返回 16console.log(pow(3));//返回 9//$("p");//默认省略document//在JQuery中的参数: $("p",document):表示在文档中查找P标签。//也可指定某个对象:$("p",document.getElementById("box")),//指定id="box"的对象下面查找p标签。</script>
3,实参>形参<script>function add(){//任何函数都有返回值,返回return后面的值,如果省略return或者return后面没有值,则返回undefinedif (arguments.length==0) return;var sum=0;for (var i = 0; i < arguments.length; i++) {sum+=arguments[i];}return sum;}console.log(add()); // 返回 undefinedconsole.log(add(1,3,4));//返回 8</script><script>// 输入任意个数字参数,输出最小值function mix(){var len=arguments.length;if (len==0) return;if (len==1) return arguments[0];var mi=0;for (var i = 1; i < len; i++) {//思路决定出路// 这里是精华所在,前后对比,把较小的一个赋值给arguments[i]arguments[i]= arguments[i-1]<arguments[i]?arguments[i-1]:arguments[i];mi = arguments[i];}return mi;}console.log(mix(1,3,444,2,5245,7373,2452,-11,-23432,-234,-245));console.log(mix());console.log(mix(888))</script>
//arguments//参数是每个函数都有的,是一个局部变量//类数组对象,但不是数组的实例。可以使用arguments[index]进行取值.<script>//合法标识符:不能以数字,关键字,保留字开头,以字母,数字,下划线组成的字符串;//这里arguments的索引是 "0" 到 "5" ,数字是不合法的标识符,所以只能使用双引号。//以下就是类数组对象:var arguments={"0":"argument1","1":"argument2","2":"argument3","3":"argument4","4":"argument5","5":"argument6"};//遍历arguments类数组对象for(var p in arguments){console.log(p+":"+arguments[p]);}
//1.对象的长度不能用.length获取,用js原生的Object.keys可以获取到console.log(arguments.length);//返回 undefinedvar keys=Object.keys(arguments)//使用原生Object.keys,获取键值对中键的集合,都是数组var values=Object.values(arguments)//使用原生Object.values,获取键值对中值的集合,都是数组console.log(keys.length);//两种都可以获得对象的长度console.log(values.length);//两种都可以获得对象的长度//但是,如果arguments作为函数中的参数,是可以通过arguments.length获得实际参数个数。//函数是一个特殊对象,也可以通过add.length 获得形式参数个数<script>function add(a,b,c){console.log(arguments.length);//返回 5 调用函数是写入的实际参数console.log(add.length);//返回 3,定函数时,定义的形式参数console.log(arguments.callee.length);//返回 3 形式参数,函数固定的形式参数长度return +a + +b + +c;//一元运算符,+取正,-取负,!取反}// console.log(add(1,3,5));console.log(add(1,3,6,7,8));//返回:10 只对前面3个参数进行相加
</script>//------function fn(arguments){console.log(argument);function fn1(arguments){console.log(argument);}fn1(2);//输出2}fn(1);//输出1//arguments是每个函数中独有的,不同作用域不同//预解析:/*fn函数作用域:var argument=undefined;fn1函数作用:var argument=undefined;*/</script>//--------// "use strict" //表示使用严格模式// var num=1;//这样定义num变正确// num=1;//这样定义num变就会报错</script><script>//判断传入参数是否等于实际参数function add(a,b){//console.log(arguments.length);//返回 5实际参数,我们实际传入的参数//console.log(arguments.callee.length);//返回 2 形式参数,函数固定的形式参数// console.log(add.length);返回 2 //形式参数,函数固定的形式参数,可以在函数外面进行调用if (arguments.length!==add.length) throw new Error("请输入:"+add.length+"个参数");return a+b;}// console.log(add(2,4));//返回 6console.log(add(1,3,4,5,6));//参数不对,参数过多。返回:text2.html:13 Uncaught Error: 请输入:2个参数</script>//---------------<body>    <p id="test" style="background-color: red; color: blue;">我是一个段落!</p><script type="text/javascript"> //在使用参数给对象设置CSS属性时,都是用p.style[property]=value,这样绝对没错//如果使用p.style.property=value。读取时使用,设置时有可能会报错。var p=document.getElementById('test');function css(value,property){//必要参数一定要放在第一个,可传可不传放在后面if (arguments.length<=0 || arguments.length>=3) throw new Error("请输入:"+arguments.length+"参数");if (property==undefined) p.style.backgroundColor=value;if (arguments.length==2) p.style[property]=value;}css("orange");//第二个参数省略,默认 property=undefined// css("green","backgroundColor");</script> </body> <script type="text/javascript"> //-----什么可以当做变量-------//1,什么都不传var a=2;function fn(){function(){alert(a);}}//2,数字function fn(num){console.log(num);}fn(2);//3,字符串//4,booleanfunction a(){}function b(){}//如果传进来的是布尔值,一定使用要把细节封装成a,b函数。经验之谈。function fn(boolean){if (true) {a();}else{b();}}//5,undefinedfunction add(a,b){if (b==undefined) return a;return a+b;}console.log(add(6,undefined));//返回 NaN,非数字function pow(bace,power){//短路操作,如果power=power=true则power=power  power=undefined=false 则power=2。power=power || 2;return Math.pow(bace,power);}console.log(pow(3,6));//6,null//以上都是单个参数传递////7,传多个参数,如数组:[1,2,3,4,5]$.each([1,2,3,4,5], function(index, val) {console.log(index);console.log(val);});for (var i = 0; i < [1,2,3,4,5].length; i++) {console.log(index);console.log(val);}//8,传对象:{"a":"1","b":"2","c":"3"}$.each({"a":"1","b":"2","c":"3"}, function(index, val) {console.log(index);console.log(val);});
//下面代码使用对象作为参数进行代码优化:function setPerson(name,sex,age,add,phone){var person={};person.name=name;person.sex=sex;person.age=age;person.add=add;person.phone=phone;}//可读性,可写性不强,很容易弄错参数顺序导致错误,所以下面可以使用对象代替setPerson("zhengl","male",18,"中国China","182...");
//当参数超过三个或者三个以上,建议适用对象进行代码优化如下:var person={};function setPerson(obj){person.name=obj.name || "xh";//如果没有设置该属性,则设置一个默认值person.age=obj.age || 18;//如果没有设置该属性,则设置一个默认值person.add=obj.add || "中国China";//如果没有设置该属性,则设置一个默认值person.sex=obj.sex || "male";//如果没有设置该属性,则设置一个默认值person.phone=obj.phone || "110";//如果没有设置该属性,则设置一个默认值}//经过代码优化:对象属性不用按顺序进行书写,甚至不写都不会报错。setPerson({name:"zheng",age:18,sex:"male"// add:"中国China", 两个属性值没写,使用默认值// phone:"187" 两个属性值没写,使用默认值});console.log(person.age);console.log(person.add);console.log(person.phone);
//9,函数作为参数,就叫回调函数$.each(obj,function(){...})setInterval(function(){},1000)</script> <script type="text/javascript"> /*//--------返回值:-------- return 1,表示 函数的结束。2,表示 返回return 后面的值。如果后面没有值,则返回undefined
return 表示在函数中使用,函数返回一个值。
continue 用于循环,表示跳出本次循环,执行下一次循环
break  跳出整个循环,执行循环以外的代码*/
//1,没有返回值: 默认undefinedfunction fn(){}function fn1 () {return;//表示返回值为undefined}function fn2(a,b){if (b<0) return;//表示函数结束执行return a/b;//表示返回值}console.log(fn());//返回 undefinedconsole.log(fn1());//返回 undefined//2,数字做返回值//3,字符串作为返回值alert(1,2,3,4);返回字符串:1,2,3 alert([1,2,3,4]);//返回字符串:1,2,3 默认会隐式转换:[1,2,3,4].toString();alert([1,2,3,4].toString());返回字符串:1,2,3//4,boolea  return true/false//5,null//6,数组 返回多个值function fn(a,b){return [a+b,a,b];}//7,对象function getPerson(){return {//不用创建对象了,直接返回一个对象即可name:"zheng",age:18};}console.log(getPerson());//{name: "zheng", age: 18}
//一下代码风格要小心,return在解析时,系统会自动给return添加分号;,从而报错。/*function getPerson(){return //return在解析时,系统会自动给return添加分号;,从而报错。{name:"zheng",age:18};}console.log(getPerson());//{name: "zheng", age: 18}*///8,函数function fn(){return function (){console.log("one");}}// 返回:// ƒ fn(){// return function (){// console.log("one");// }// }console.log(fn);//返回:ƒ (){ console.log("one"); }console.log(fn());//返回:oneconsole.log(fn()());//------document.write([1,3,5]);//返回 1,3,5 进行了隐式转换[1,3,5].toString();document.write({"name":"zheng","age":18,toString:function(){document.write("love");}});//返回:[object Object]console.log({"name":"zheng","age":18,function(){document.write("love");}});//返回:{name: "zheng", age: 18, function: ƒ}
/*为了写出更优雅的函数,会将函数作为参数传递到另一个函数中,组成一个新功能的函数:两个功能:1,传进来函数的功能。2,接收函数的功能。一个函数实现一个功能,把多个函数组合成一个新的函数,就实现了一个复合的功能。*/</script>    //------关于局部作用域,调用一次就创建一次,也删除一次-------<script type="text/javascript"> function count(){ var num=1; return function(){ return num++;//先返回 num,再num+1 // return ++num;//先num+1,再返回 num } } console.log(count()());//每次调用普通函数,都会创建一个新的局部作用域,函数执行完连被删除 console.log(count()());//每次调用普通函数,都会创建一个新的局部作用域,函数执行完连被删除 console.log(count()());//每次调用普通函数,都会创建一个新的局部作用域,函数执行完连被删除 var fn=count();//这里只调用一次函数,只开辟一个局部作用域,所以里面的num执行几次就会加1几次。 console.log(fn());//fn()=count()(); console.log(fn());//fn()=count()(); console.log(fn());//fn()=count()(); //返回:1 ,1 ,1 ,1 ,2 ,3  // 1、 count()()这样调用,每次都会创建一个新的局部作用域,num的值会不断地被初始化为1
 // 2、 return num++表示先返回num的值,再将num加1
 // 3、 先将count()赋给fn,此时count()只调用了一次,接下来多次调用fn()的时候,count函数并没有多次调用,num只会在count函数调用的时候被初始化,所以多次调用fn()的时候num不会被多次初始化;由于fn相当于count函数的内层函数(var fn=count();这行代码执行后,就调用了count(),调用count后就将里面的函数赋值给了fn,所以说fn就相当于函数的内层函数了。),可以访问count中的变量num,所以多次调用fn函数,会将num的值累加;</script> 

posted @ 2019-06-02 22:01  最好的安排  阅读(303)  评论(0编辑  收藏  举报

Knowledge is infinite