深入对象
函数深入理解
函数的定义方式
函数是一个非常特殊的对象,也是Function
类的一个实例;内存中存储的操作是通过一个键值对来存储;有三种定义方式如下:
//第一种定义方式
function fn1() {
alert("fn1");
}
alert(typeof fn1);// function 也是一种数据类型
//第二种创建方式
var fn2 = function() {
alert("fn2");
}
//第三种创建方式
var fn2 = new Function('num1','num2',"alert('fn3:'+num1+num2)");
fn2(11,12); //23
函数和对象的区别
虽然函数也是一个对象,但是和对象有一些区别:
- 对象是通过引用指向对象来完成赋值
function fn1() {
alert("fn1");
}
var fn2 = fn1;
fn1 = function() {
alert("fnn1");
}
fn2();//fn1
fn1();//fnn1
- 函数是通过对象的拷贝来完成赋值
var o1 = new Object();
var o2 = o1;
o2.name = "c10";
alert(o1.name);
函数的重载
JavaScript
中没有函数重载,函数会在堆中复制原来的函数并指向新的内存地址,两个函数的内存地址不相同,而变量是指向后面复制的函数的,原来的函数没有对象指向。
function sum(num1,num2) {
return num1+num2;
}
function sum(num1) {
return num1+100;
}
//一下两个值都为119
alert(sum(19));
alert(sum(19,20));
函数的值传递
函数作为参数传递
由于函数是function
对象,可以直接把对象作为参数传递。
function callFun(fun,arg){
return fun(arg);
}
var say = function(str) {
alert(str+":hello");
}
say(yjl);
callFun(say,yjl)
函数作为返回值传递
function fn1(arg) {
var rel = funciton(num) {
return arg+num;
}
return rel;
}
var f = fn1(20);
alert(f);
alert(f(140));
数组sort()
方法分析
sort()
默认只能对字符串进行排序操作,如果对数字或者字符串数字进行操作,需要提供比较函数,比较函数应该具有两个参数a和b,其返回值如下:
array.sort(sortby);//sortby 必须是函数
- a > b return 1;
- a == b return 0;
- a < b return -1;
var p1 = new Person("Jhon",23);
var p2 = new Person("Leno",29);
var p3 = new Person("Ada",41);
var ps = [p1,p2,p3];
//年龄排序
function sortByAge(a,b) {
return a-b;
// 如果是字符串数字 [‘1’,‘2’,‘3’,‘4’];
// return parseInt(a-b);
}
//姓名排序
funciton sortByName(a,b) {
if(a.name>b.name) return 1;
else if(a.name == b.name) return 0;
else return -1;
}
//函数作为参数传递
ps.sort(sortByAge);
ps.sort(sortByname);
以上方法可以实现不同的排序,但是还不够灵活,希望通过使用一个函数更具传入的参数,就能按照参数的类型进行排序,如果传入年龄,自动按照年龄进行排序。
//函数作为返回值
function sortByProperty(propertyName) {
var sortFun = function(obj1,obj2) {
if(obj1[propertyName]>obj2[propertyName]) return 1;
else if(obj1[propertyName]=obj2[propertyName]) return 0;
else return -1;
}
}
ps.sort(sortByProperty('name'));
ps.sort(sortByProperty("age"));
补充:属性的调用有两种方式
- 对象.属性
- 对象[属性]
function Person(name,age) {
this.name = name;
this.age = age;
this.address = "云南";
//方法的创建
this.say = function() {
alert(this.name+":哈哈哈")
}
}
for(var i in p1) {
//可以获取对象显示声明的对象
//alert(i); // 输出所有属性
//获取对象属性和值 如果使用p1.i 回去找person中属性i,都没有定义,返回值为undefine
alert(i+":"+p1[i]);
}
同理如果上面使用obj1.propertyName
方式来获取属性,回去Person
对象中找propertyName
属性,我们并未设置,结果肯定为undefined
。
函数的内部属性
arguments.callee()
arguments
对象用来可以获取相应的参数值,是一个数组;它的callee()
方法可以反向调用。
function factorial(num) {
if(num===1) {
return 1;
}
// 函数的解耦合
// return num*factorial(num-1);
return num*arguments.callee(num-1);
}
var cf = factorial;
//不会报错
alert(cf(5));
factorial = null;
// 此时由于cf这个函数内部仍然调用factorial() ,factorial已经指向空了。
// 如上情况只能使用arguments.callee(arg),函数名已更改,内部的函数名也随之改动
alert(cf(5));
如果函数使用递归地情况下,外部名函数改变,就会报错,如用
argumenta.callee()
反调用外部函数,就能保持函数内外一致。
this
指向当前对象,可以用来设置当前对象的属性或者方法;特别注意this会更具对象调用的不同,所指向的对象也不同。
var color = "red";
function showColor() {
alert(this.color);
}
function Circle(color) {
this.color = color;
this.showColor = showColor;
}
var c = new Circle("yellow");
// 使用c调用showColor();
c.showColor();
// 直接掉用showColor函数
showColor();
函数的常用属性和方法
-
length
查看函数中参数的个数。
function fn1() {
}
function fn2(num1,num2) {
}
function fn3(num1) {
}
alert(fn1.length); //0
alert(fn2.length); //2
alert(fn3.length); //1
call(调用上下文,参数数组)
var color = "red";
function showColor() {
alert(this.color);
}
function Circle(color) {
this.color = color;
//this.showColor = showColor;
}
var c = new Circle("yellow");
showColor.call(this);// 使用上下文调用,this指向windows对象,red
showColor.call(c); //yellow
/*
*通过以上发现,使用call和apply之后,对象可以不需要定义方法
* 通过apply或者call来调用对象
* */
apply(调动上下文,参数1,参数2)
function sum(num1,num2) {
return num1+num2;
}
function callSum1(num1,num2) {
// 使用sum这个函数来完成一次调用,调用的参数就是callSum1这个函数的参数
//apply 表示一组参数数组
return sum.apply(this,arguments);
}
function callSum2(num1,num2) {
return sum.apply(this,[num1,num2])
}
function callSum3(num1,num2) {
//call是通过参数列表来完成传递,其他和apply没有任何区别
return sum.call(this,num1,num2);
}
alert(callSum1(12,22));
alert(callSum2(33,22));
alert(callSum3(1,2));