函数一种对象,函数中可以封装功能,使用typeof检查一个函数对象的时候,会返回function
创建一个函数对象
var function = new Function();
可以将要封装的代码以字符串的形式传递给构造函数
var function = new Function("console.log('xxxxxxxx');");;
调用函数的语法:函数对象(),function()
使用函数声明来创建一个函数
语法:
function 函数名称(形参列表){
函数体;
}
使用函数表达式来创建一个函数:
语法:
var fun = function(形参列表){
函数体;
}
调用函数时候,解析器不会检查实参的类型,也不会检查实参的数量,多余的实参不会被赋值,实参个数小于形参的个数,没有赋值的形参将是undefined
return 后面不写,相当于返回undefined,如果不写return 语句,则也会返回一个undefined
return的返回值可以是任何类型,可以是对象,也可以是函数
function fun3(){
//在函数内部再声明一个函数
function fun4(){
alert("我是fun4");
}
//将fun4函数对象作为返回值返回
return fun4;
}
a = fun3();
//a();
fun3()();
立即执行函数:
function(){
alert("xxxxxx");
}
//以上是错误写法
(function(){
alert("xxxxxx");
})();
//立即执行
枚举对象中的属性
for(var n in obj){
console.log("属性名:"+n);
console.log("属性值:"+obj[n]);
}
全局作用域:直接编写在script标签中的js代码,都是全局作用域,在页面打开创建,在页面关闭销毁,在全局作用域中有一个全局对象window(代表浏览器的一个窗口,由浏览器创建)
在全局作用域中,创建的变量都会作为window对象的属性保存
使用var声明的的代码,会在所有的代码之前被声明,但是不会赋值(变量的声明提前)
函数的声明提前:
//fun();
//fun2();//这行报错,此时的fun2=undefined;
//函数声明,会被提前创建
function fun(){
console.log("我是一个fun函数");
}
//函数表达式,不会被提前创建
var fun2 = function(){
console.log("我是fun2函数");
};
fun2();
使用函数声明形式创建的函数function,会在所有的代码执行之前就被创建,所以可以在函数声明之前进行调用
使用函数表达式创建的函数不能被创建
全局作用域中的变量都是全局变量,在页面的任意部门都可以进行访问
函数作用域:调用函数时候创建函数作用域,函数执行完毕后,函数作用域被销毁,每调用一次就会创建一个新的函数作用域,他们之间是相互独立的
在函数作用域中可以访问到全局作用域的变量,在全局作用域中无法访问到函数作用域中的对象
当在函数作用域中操作一个变量时候,首先在函数作用域中进行寻找,知道找到全局作用域中,如果全局作用域中也没有,则会报错
在函数作用域中要访问全局变量,可以使用window对象
在函数作用域也有声明提前的特性:使用var关键字声明的变量,会在函数中所有的代码执行之前被声明,函数声明也会在函数中的所有代码之前执行
var c = 33;
function fun5(){
console.log("c = "+c);
var c = 10;
}
fun5();//输出undefined
var c = 33;
function fun5(){
console.log("c = "+c);
c = 10;
//d没有使用var关键字,则会设置为全局变量
d = 100;
}
fun5();
//在全局输出c
console.log("c= "+c); //10
console.log("d= "+d);//100
解析器在调用函数每次都会向函数传递一个隐含的参数,这个隐含的参数就是this,this指向的是一个对象,这个对象称为函数执行的上下文对象,根据函数的调用方式的不同,this会指向不同的对象
function fun(){
//console.log("a = "+a+", b = "+b);
console.log(this.name);//window
}
以函数的方式调用,this代表window, 以方法的形式的调用,this就是调用方法的哪个对象
<script type="text/javascript">
function fun(){
//console.log("a = "+a+", b = "+b);
console.log(this.name + "=====" + this);
}
//fun();
//创建一个对象
var obj = {
name:"Tom",
sayName:fun
};
var obj2 = {
name:"jacky",
sayName:fun
};
console.log(obj.sayName == fun); //true
obj.sayName();//以方法的形式调用,this是调用方法的对象 Tom=====[object Object]
fun();//以函数形式调用,this是window ===》window.fun() =====[object Window]
</script>
//创建一个name变量
var name = "全局";
//创建一个fun()函数
function fun(){
console.log(name);//永远都是"全局"
console.log(this.name);
}
//创建两个对象
var obj = {
name:"Tom",
sayName:fun
};
var obj2 = {
name:"Jacky",
sayName:fun
};
obj.sayName();
obj2.sayName();
使用工厂方法创建对象:使用工厂方法创建对象,使用的构造函数都是Object,所以创建的对象都是Object类型,导致我们无法区分出多种类型的对象
/*
* 使用工厂方法创建对象
* 通过该方法可以大批量的创建对象
*/
function createPerson(name , age ,gender){
//创建一个新的对象
var obj = new Object();
//向对象中添加属性
obj.name = name;
obj.age = age;
obj.gender = gender;
obj.sayName = function(){
alert(this.name);
};
//将新的对象返回
return obj;
}
构造函数和普通函数的区别:
构造函数使用new关键字进行调用,普通函数直接调用
function Person(){
}
var preson = Person();
var person2 = new Person();
console.log(preson); //undefined
console.log(person2); //Person {}
构造函数的执行流程:
1、立即创建一个新的对象
2、将新建的对象设置为this,在构造函数可以使用this来引用新建的对象
3、逐行执行构造函数的对象
4、将新建的对象返回
通过构造函数创建的一类对象称为实例
console.log(typeof person2); // object
console.log(person2 instanceof Person); //true //instanceof 可以检验一个实例是否属于某个类
console.log(person2 instanceof Object);//true
call()和apply()这两个方法都是函数的方法,需要通过函数进行调用,当对函数调用call()和apply()方法,都会执行函数,可以将一个对象指定为第一个参数,此时this将称为指定的参数对象
function fun() {
console.log(this.name);
}
fun.call({name:"Tom"});//Tom
fun.call({name:"Jacky"});//Jacky
function fun2() {
console.log(this.name);
}
function fun(a,b) {
console.log("a = "+a);
console.log("b = "+b);
}
/*
* call()和apply()
* - call()方法可以将实参在对象之后依次传递
* - apply()方法需要将实参封装到一个数组中统一传递
*
* - this的情况:
* 1.以函数形式调用时,this永远都是window
* 2.以方法的形式调用时,this是调用方法的对象
* 3.以构造函数的形式调用时,this是新创建的那个对象
* 4.使用call和apply调用时,this是指定的那个对象
*/
fun.apply({name:"Tom"},[2,3]);
fun.call({name:"Jacky"},2,3);
arguments参数:
/* * 在调用函数时,浏览器每次都会传递进两个隐含的参数: * 1.函数的上下文对象 this * 2.封装实参的对象 arguments * - arguments是一个类数组对象,它也可以通过索引来操作数据,也可以获取长度 * - 在调用函数时,我们所传递的实参都会在arguments中保存 * - arguments.length可以用来获取实参的长度 * - 我们即使不定义形参,也可以通过arguments来使用实参, * 只不过比较麻烦 * arguments[0] 表示第一个实参 * arguments[1] 表示第二个实参 。。。 * - 它里边有一个属性叫做callee, * 这个属性对应一个函数对象,就是当前正在指向的函数的对象 * */ function fun() { console.log(arguments); //Arguments(2) ["hello", "world", callee: ƒ, Symbol(Symbol.iterator): ƒ] console.log(arguments instanceof Array); //false console.log(arguments.length); //2 console.log(Array.isArray(arguments)); //false console.log(arguments.callee); /* ƒ fun() { console.log(arguments); //Arguments(2) ["hello", "world", callee: ƒ, Symbol(Symbol.iterator): ƒ] console.log(arguments instanceof Array); //false console.log(arguments.… */ } fun("hello", "world");