函数的三种定义方式
在同一个script标签中,函数会有函数提升特性,但是在不同的script中只是后面的能调用前面的
定义命名函数
定义匿名函数
匿名函数的可读性更好,也是最常用的方法
利用Function类匿名函数
可读性很差!!!!!
局部函数
函数、方法、对象、变量和类
函数的实例属性和类属性
代码示例:
Person类的age是成员变量,national是静态变量,bb是局部变量(外界访问不到)
<script>
function Person(national ,age){
this.age=age;
Person.national = national;
var bb=0;
}
var p1 = new Person("中国",29);
document.writeln("第一个Person对象<br/>");
document.writeln("p1年龄是:"+p1.age+"<br/>");
document.writeln("p1国籍是:"+p1.national+"<br/>");
document.writeln("通过Person访问静态national属性为"+Person.national+"<br>");
document.writeln("p1的bb属性为:"+p1.bb+"<br><hr>");
var p2 = new Person("美国",38);
document.writeln("创建两个对象之后<br/>");
document.writeln("p1年龄是:"+p1.age+"<br/>");
document.writeln("p1国籍是:"+p1.national+"<br/>");
document.writeln("p2年龄是:"+p2.age+"<br/>");
document.writeln("p2国籍是:"+p2.national+"<br/>");
document.writeln("通过Person访问静态national属性为"+Person.national+"<br>");
document.writeln("p1的bb属性为:"+p1.bb+"<br><hr>");
</script>
调用函数的三种方式
直接调用函数
以call()方法调用函数
代码示例:
each的函数还传进去一个fn函数,但是定义each的时候并没有定义fn函数,所以无法直接调用。
<script>
var each = function(array,fn){
for (var index in array) {
fn.call(null,index,array[index]);
}
}
each([4,20,3],function(index,ele){
document.writeln("第"+index+"个元素是:"+ele+"<br>")
})
</script>
以apply()方法调用函数
函数的独立性
也就是说,虽然函数可能定义在某个类中,但是其并不属于该类,是一个独立的个体,任何别的类的对象同样也可以调用它
代码示例:
<script>
//函数独立性
function Person(name){
this.name=name;
this.info= function(){
alert("我的name是:"+this.name);
}
}
var p = new Person("法外狂徒张三");
p.info();
var name = "我是李四";
p.info.call(window);
</script>
从上面代码看出,虽然info定义在person类中,但是通过Window对象仍然能调用它,输出了Window对象的name
代码示例:
<script>
function Dog(name ,age,bark){
this.name=name;
this.age=age;
this.bark=bark;
this.info = function(){
return this.name+"的年龄为"+this.age+",它的叫声:"+this.bark;
}
}
var dog=new Dog("旺财",3,"嗷嗷嗷嗷");
function Cat(name,age){
this.name=name;
this.age=age;
}
var c=new Cat("汤姆",2);
alert(dog.info.call(c));
</script>
函数提升
普通函数和局部函数会直接提升,匿名函数会把被赋值的变量提升到顶部,而不会把函数本身提升,提前使用会出错
函数和变量同名的覆盖问题
变量如果有初值,变量优先级更高;反之函数优先级更高
箭头函数
代码示例:
<script>
var arr = ["张三","李四","王二麻子","PDD"];
var newArr1 = arr.map(function(ele){
return ele.length;
})
var newArr2 = arr.map((ele) => {
return ele.length;
})
var newArr3 = arr.map(ele => ele.length);
console.log(newArr3);
arr.forEach(function (ele){
console.log(ele);
})
arr.forEach( (ele) =>{
console.log(ele);
})
arr.forEach(ele => console.log(ele));
</script>
this关键字问题
与普通函数不同的是,箭头函数并没有自己的this关键字。箭头函数中的this关键字是其函数外层的对象的this
普通函数的this:
<script>
function Person(){
this.age = 0;
setInterval(function growUp(){
console.log(this === window);
this.age++;
},1000);
}
var p = new Person();
setInterval(function(){
console.log(p.age);
},1000)
</script>
箭头函数的this:
<script>
function Person(){
this.age = 0;
setInterval(() => {
console.log(this === window);
this.age++;
},1000);
}
var p = new Person();
setInterval(function(){
console.log(p.age);
},1000);
</script>
代码示例:
代码中的arguments指的是传入f函数的参数数组,与那些字符串并没有关系,第一个return arguments[2],也就是9
所以执行结果是hello,9
<script>
function foo(){
var f = function(i){return 'Hello,'+arguments[i]};
return f(2,7,9,97,0);
}
console.log(foo("guoshuai","qingcheng","xueshu",'yuwen'));
</script>
代码示例:
代码中的arguments指的是传入foo函数的参数数组,第一个return arguments[2],也就是xueshu
所以执行结果是hello,xueshu
<script>
function foo(){
var f = (i) => {return 'Hello,'+arguments[i]};
return f(2,7,9,97,0);
}
console.log(foo("guoshuai","qingcheng","xueshu",'yuwen'));
</script>
箭头函数容易引发的错误
函数的参数传递
代码示例:
传递的时候是把person拷贝了一份成为person1传递过去,而person指向的对象{age:15}并没有改变,也就是person和person1都指向该对象,通过函数把age改为10,然后函数中的person1指向变为null。但是person并没有影响,所以person还是个对象
<script>
function changeAge(person){
person.age=10;
document.writeln("函数执行中person的age值为:"+person.age+"<br>");
person = null;
}
var person = {age:15};
document.writeln("函数调用前person的age值为:"+person.age+"<br>");
changeAge(person);
document.writeln("函数调用之后person的age值为:"+person.age+"<br>");
document.writeln("person对象为:"+person+"<br>");
</script>
空参数问题
同名的函数会产生覆盖,而不是重载
即传入参数之后先进性判断能不能满足该函数的需求,如果满足,就继续执行;不满足就跳出