函数
函数是一个对象。
typeof
检查时,返回function
- 构造函数创建函数对象。封装的代码以
字符串
的形式传递给构造函数。但不是非要加“”
var func = new Function("console.log('构造函数');");
这个构造方式可以使用console.log(func)输出该方法的内容。function fun(){}
则不能console.log输出方法内容。
- 封装到函数中的代码不会立即执行,指挥在调用的时候执行。
- 常用的函数声明:
一:
function fun(){}二:
var fun = function(){}
函数的参数
调用函数时解析器不会检查实参的类型。
注意,是否可能会接收到非法参数,若有,则对参数进行数据类型检查
函数的实参可以是任意的数据类型
调用函数时,解析器也不会检查实参的数量。
多余实参不会被赋值
如果实参的数量少于形参的数量。没有对应实参的形参 时
undefined
实参可以是一个对象,也可以是一个函数。
返回值
return
语句后的都不执行。return;
====>没有返回值
,相当于返回undefined
- 函数没有
return
,也相当于返回undefined
return
后可以跟任意类型的值fun(miao()); //函数返回值 fun(miao); //调用函数对象 /* miao() 1.调用函数 2.《并且》<fun()>使用函数的返回值 miao 1.调用函数对象 使用函数对象 */
立即执行函数
立即执行函数只会执行一次
//匿名函数加括号表示匿名函数是一个整体.函数不会执行
(function(){
return 0;
});
//(匿名函数)();====>函数立即执行
(function(){
return 0;
})();
//立即执行函数 可以传参数
(function(a,b){
return a+b;
})(a,b);
枚举对象中的属性
- 函数可以作为一个对象的属性
如果一个函数作为一个对象的属性保存,那么称这个函数为
对象的方法
。调用这个函数成为调用这个对象的方法啊。本质和函数没有区别。只是名称上的区别。
比如:"xxx".toString();
枚举对象中的属性
使用
for(var 变量 in 对象){}
循环体中有多少属性,就会循环几次
//输出属性名
(function(){
var str = "";
for (var n in console){
str += n+" ,";
}
console.log(str);
})();
//输出属性值
(function(){
var str = "";
for (var n in console){
str += console[n]+" , ";
}
console.log(str);
})();
作用域
全局作用域
作用域:一个变量的作用范围
- 全局作用域
- 直接编写再
script
标签中的JS代码,都在全局作用域- 全局作用域再页面打开时创建,在页面关闭时销毁
在全局作用域中有一个全局变量
window
- 它代表一个浏览器的窗口,它由浏览器
创建
,可以直接使用在
全局作用域
中
- 创建的变量都会作为
window
对象的属性保存- 创建的函数都会作为
windwo
对象的方法保存全局作用域中的变量是全局变量,
- 在页面的任意部分都可以访问的到
var a=5;
- 变量声明提前
使用var关键字声明的变量,会在所有的代码执行之前被声明。【但不会被赋值】
如果声明变量时不使用var关键字,则变量不会被提前声明。
console.log("a = "+a);
var a =33; //输出 a = undefined
//相当于 ====>
var a;
console.log("a = "+a);
a = 33;
//====================
console.log("a = "+a);
a = 33; //报错 “a没有定义”
- 函数声明提前
使用函数声明形式创建的函数
function(){}
会在所有的代码执行之前就被创建。可以在函数声明前创建使用函数表达式创建的函数不会被声明提前,所以不能在声明前调用。
fun2();//输出 fun2不是一个function
fun();//输出"我是一个fun函数"
function fun(){
console.log("我是一个fun函数");
}
var fun2 = function(){
console.log("我是fun2函数");
}
函数作用域
- 调用函数时创建函数作用域,函数
执行完毕
之后,函数作用域销毁
。- 每
调用
一次函数就会创建
一个新的函数作用域,他们之间是相互独立
的- 在
函数作用域
中阔以访问到全局作用域变量。 在全局作用域无法访问到函数作用域的变量当在函数作用域操作一个变量时,它会先在自身作用域寻找,如果有直接使用。
- 如果没有则向上一级作用域中寻找,直到找到全局作用域
- 如果全局作用域中也没有,则会报错。
ReferenceError
- 在函数中要访问全局变量,阔以使用window对象。
- 在函数中,不使用
var声明
的变量都会,自动设置为**全局变量**
。
function fun(){
console.log("a = "+a);
}
var a =5;
fun(); //调用fun. 输出5
function fun2(){
var b = 6;
}
console.log("b = " +b); //ReferenceError
function fun3(){
console.log("a = "+a);
var a = 10; //======> var a; xxxxx; a=10;
}
fun3(); //输出 未定义
function fun4(){
a = 13;
H = 20;
fun5(); // a=13 ===>window.a = 13;
function fun5(){
console.log("a = "+a);
}
}
fun4(); //执行函数fun4()
console.log("H = "+ H); //H = 20; 不会提前声明H,
函数作用域中也有函数声明提前的特性,使用var关键字声明的变量,会在函数中所有的代码执行之前被声明
function fun(){
var a = 5;
fun7();
function fun7(){ //提前执行.
console.log("a = "+a); //a = 5;
}
}
定义形参,相当于在函数作用域
中声明了变量
var a =55;
function fun9(a){
console.log(a);
return a;
}
fun9(); // a ===> undefined .
function getStyle()
【兼容性问题】当浏览器是IE8时,变量
getComputedStyle
会首先在getStyle()
函数作用域寻找有木有这个function
。函数中没有,会在全局作用域寻找,也没有。则会报错。后面的代码
-----------
都不执行。
function getStyle(obj,name){
if(getComputedStyle){ //是一个变量
----------------------
//正常浏览器的方式,具有getComputedStyle()方法
return getComputedStyle(obj,null)[name];
}else{
//IE8的方式,没有getComputedStyle()方法
return obj.currentStyle[name];
}
}
function getStyle(obj,name){
if(window.getComputedStyle){ //变成了对象的属性。找不到会返回undefined
return getComputedStyle(obj,null)[name];
}else{
return obj.currentStyle[name];
}
}
函数声明
var func = new Function("console.log('构造函数');");
这个构造方式可以使用console.log(func)输出该方法的内容。function fun(){}
则不能console.log输出方法内容。
//使用function fun()
function fun(){
var a =8;
}
//var提前声明miao 数据类型undefined。等待程序 执行完这行代码,之后miao才会定义为函数并且是一个“匿名函数”?。
console.log(typeof miao);//undefined
var miao = new Function ("return 666;");
console.log(miao); // function anoymous(){xxx}
函数的方法apply,call
call()
和apply()
方法
- 这两个方法都是函数对象的方法,需要通过函数对象调用。
function fun(){}
fun();
=====>返回值,不是函数对象。
fun
====>函数对象
对函数调用这两个方法时,都会调用函数执行
fun(); ==== fun.apply(); ==== fun.call();
在调用call和apply时可以将一个对象指定为第一个参数。
此时,这个对象会成为函数执行时的
this
。
var obj1 = {name:"obj1"};
var obj2 = {name:"obj2"};
function fun(){
console.log(this.name);
}
fun.call(obj1); // obj1
参数
是谁,执行的对象
就是谁
var obj1 = {name:"obj1",sayName:function (){console.log(this.name)}};
var obj2 = {name:"obj2"};
function fun(){
console.log(this.name);
}
obj1.sayName.call(obj2); // obj2
call
方法:可以将实参在对象之后传递
apply
方法:需要将实参封装在数组中,再传递
function fun(a,b){
console.log("a ="+a);
console.log("b ="+b);
}
var obj1 = {name:"obj1",sayName:function (){console.log(this.name)}};
var obj2 = {name:"obj2"};
//`call`方法:可以将实参在对象之后传递
fun.call(obj1,3,4); // a = 3,b = 4
//apply 方法需要将实参封装到数组中
fun.apply(obj1,[3,4]); // a = 3,b = 4
arguments
arguments
对象不是一个Array
。它类似于Array
,但除了length属性和索引元素之外没有任何Array
属性。- 在调用函数时,传递的实参都会保存在
arguments
中arguments.length
可以用来获取实参的数量所以即使不定义形参,也可以通过
arguments
来使用实参。
- arguments[0] ====> 第一个实参
- arguments[1] ====> 第二个实参
arguments
有一个属性:callee
- 这个属性对应一个函数对象,就是当前正在执行的函数对象
function fn( a , b){
console.log(a+b);
console.log(arguments.length);
console.log(arguments.callee);
}
fn(1,3,4,5,6);
/*
4
5
[Function: fn]
*/