JavaScript 你应该知道的知识
今天醒的比较早,闲着没事,翻来js书看看, 不料有很多意想不到的收获,和大家分享!
在函数体内获取 参数(学了这么长时间,才知道有这个东西,悲催啊,我还经常纳闷,为啥那些编好的js库里,我找不到参数的用途)
<script type="text/javascript">
function a() {
if (arguments.length > 0) {
for (i in arguments) {
alert(arguments[i]);
}
}
}
window.onload = a(1, 2, 3, 4, 5);
</script>
既然可以获取到 参数,那么就可以 对传入的参数 进行验证, 正则也好,规定参数类型也好, 就都可以实现了,增加了函数的容错功能.
下面来看获取 函数 形参,和实参数目的例子:
<script type="text/javascript">
function a() {
var arguments1 = arguments.length; //获取实参的个数
var arguments2 = arguments.callee.length; // 获取形参的数目
//在 非匿名函数下, 可以使用 函数名.length获取形参 个数. 本例是 a.length
document.write("实参个数:" + arguments1 + "</br>" + "形参个数:" + arguments2);
}
window.onload = a(1, 2, 3, 4, 5);
</script>
正确理解 this
学习 this 之前,首先 要弄明白什么是 调用者和 所有者的概念.
所谓调用者就是 调用函数的域( 变量域,对象的属性域),
所有者 就是 调用函数的对象.
定义一个函数:
function a(s){ return s;}
var b=a; //把函数a 赋值给变量b
var o= { x:f} //把函数赋值给 对象o的 x属性
把函数a赋值给 变量b,则 变量域b就是 函数a的调用者. 此时变量b存储着 函数a的地址,同理,对象o的x属性域 也存储着函数a的引用地址,所以他们被称为调用者.
而 变量e属于全局对象 window所有,此时 window便是函数f的所有者,同理,o对象的x属性,属于o对象所有,所以o也是 函数a的所有者.
理解这些之后,在来看 this,
一般来说,在函数被调用过程中,关键字 this总是指向 函数的所有者.
下面看一个例子:
var x=1;
function f(){ this.x=2;}
f(); //调用 函数f
alert(x); //此时 弹出 2
通过调用函数f, 函数内部的关键字this指向的对象 是 window,所以 this.x就 等效于 window.x ,于是 它就覆盖了 全部变量 x的值.弹出2
下面在举一个 例子:
function f(){
this.x= function(x){return x}
}
f(); //调用函数f
alert(f.x(4)); //此时 会返回编译错误 f.x is not a function
那么 使用 alert(window.x(4)); 则会 弹出 4,这是为什么呢,下面解释一下:
虽然方法x在 函数f体内定义,但是它已经不属于函数f了, 因为window是 函数f的所有者,而 this就是指向 window的,所有 x方法 是window的方法.
不过 我们可以 借助 new在 实例化 函数f,则此时 函数f变成了 一个对象类,实例化以后 this指向的就是本对象了,而不是window了
function f()
{
this.x=function(s){ return x;}
}
var a=new f();
alert(a.x(4)); //此时 弹出4
动态 调用函数: call() 和apply()方法
function a(a, b) { return a + b; }
function o(a, b) {return a * b;}
alert(a.call(o, 3, 4));
通过 call方法, 把函数a绑定到 o这个伪对象上,作为 o的一个方法 出现,然后动态 调用该方法.
那么也可以转换为下面的的代码:
function a(a, b) { return a + b; }
function o(a, b) {return a * b;}
o.f=a;
alert(o.f(3, 4)); //弹出7
delete o.f; // 删除o对象的f方法
下面在看一 apply()的用法:
其实 apply和call本有本质的区别,只是 apply()传递的参数 是以 数组的形式 传递的.
function a(a, b) { return a + b; }
function o(a, b) {return a * b;}
alert(a.call(o, [3,4])); //弹出7
这两个函数给开发带来很多便利:看下面的代码:
求数组的最大值:
var a = [1, 2, 34, 233, 111];
var m = Math.max.apply(Object, a);
alert(m);
把系统函数 Math.max方法 做为 object方法来使用,
好处: 通过调用 call()和apply()动态调用函数 可以用完之后马上删除,避免资源占用,可以实现灵活的调用.
代码证明,动态调用函数后,马上删除:代码如下:
function f(){}
f.call(Object);
Object.f(); // 运行一下, 编译失败……Object.f is not a function
call()和apply()延伸 之高级用法:
call()和apply()在js手册这样定义:调用一个对象的一个方法,以另一个对象替换当前对象.
其实就是改变对象的 this 所 指向的内容.
<script type="text/javascript">
var x = "a";
function b() { this.x = "b"; }
function f() { alert(this.x); }
window.onload = function () {
f();
f.call(new b());
};
</script>
上述代码会弹出2次.一次是 a,一次是b. 就是 通过call()改变了 this的指向.
第二种用法(很霸道…)
<script type="text/javascript">
function f() {
this.a = "a";
this.b = function () { alert("b"); }
}
function e() {
f.call(this);
b();
}
window.onload = e;
</script>
通过 f.call(this) 相当于把 f的属性a和方法拷贝到 e中,以供调用.是不是很强大……
本质上将 就是 更改了 f函数内部关键字 this的指向了e,这样e就可以引用 函数f内的成员了.