Javascript有三种执行体,一种是eval()函数入口参数中指定的字符串,该字符串总是被作为当前函数上下文中的语句来执行,第二种是new Function(){}中传入的字符串,该字符串总是被作为一个全局的,匿名函数闭包中的语句行被执行;第三种情况执行体就是一个函数,可以通过函数调用运算符”()”来执行;除了以上三种之外,我们现在还可以使用call()方法或者apply()方法作为动态方法来执行;如下代码:
function foo(name){ alert("hi:"+name); } foo.call(null,'longen'); // 调用打印 hi: longen foo.apply(null,['tugenhua']); // 调用打印 hi:tugenhua
call()方法与apply()方法 使用效果是一样的,都是调用函数,只是第二个参数不一样,apply第二个参数是一个数组或者arguments;
在call和apply中理解this的引用
如果我们将一个普通的函数将作为一个对象的方法调用的话,比如我现在有一个普通的函数如下代码:
function foo(){ alert(this.name); }
现在我们下面定义2个对象如下:
var obj1 = {name:'obj1'};
var obj2 = new Object();
obj2.name = 'obj2';
那么现在我们使用这2个对象来分别调用哪个上面的普通函数foo;如下:
foo.call(obj1);
foo.call(obj2);
可以看到,第一次打印的是obj1,第二次打印的是obj2;也就是说第一次的this指针指向与obj这个对象,第二次this指针指向与obj2这个对象;
下面是代码:
function foo(){ alert(this.name); } var obj1 = {name:'obj1'}; var obj2 = new Object(); obj2.name = 'obj2'; foo.call(obj1); // obj1 foo.call(obj2); //obj2
我们在方法调用中能查询this引用以得到当前的实例,因此我们也能够使用的下面的代码来传送this的引用;
比如如下代码:
function foo(){ alert(this.name); } function MyObject(){ this.name = 'myObject'; } MyObject.prototype.doAction = function(){ foo.call(this); } // 测试 var obj3 = new MyObject(); obj3.doAction();
如上代码先实例化MyObject这个对象,得到实例obj3, 然后调用实例的doAction这个方法,那么当前的this指针就指向了obj3这个实例,同时obj3.name = ‘MyObject'; 所以在调用foo.call(this)时,this指针指向与obj3这个实例,因此alert(this.name);就弹出myObject;
使用同样的方法,我们可以传递参数,代码如下:
function calc_area(w,h) { alert(w*h); } function Area() { this.name = 'MyObject'; } Area.prototype.doCalc = function(v1,v2){ calc_area.call(this,v1,v2); }; var area = new Area(); area.doCalc(10,20);
如上使用了call方法,并且给call方法传递了2个参数,但是上面的我们也可以使用apply()方法来调用,我们知道apply()方法和call()方法的不同点就是第二个参数,如上call方法的参数是一个一个的传递,但是apply的第二参数是一个数组或者是arguments,但是他们实现的功能是相同的;
function calc_area(w,h) { alert(w*h); } function Area() { this.name = 'MyObject'; } Area.prototype.doCalc = function(v1,v2){ //calc_area.call(this,v1,v2); calc_area.apply(this,[v1,v2]) }; var area = new Area(); area.doCalc(10,20);
理解javascript对象
Object.defineProperty方法, 该方法是ECMAScript5提供的方法,该方法接收3个参数,属性所在的对象,需要修改对象中属性名字,和一个描述符对象;描述符对象的属性必须是 configurable、enumerable、writable 和value。设置其中的一或多个值,可以修改对应的特性值。
ECMAScript中有2种属性,数据属性和访问器属性
1. 数据属性;
数据属性包含一个数据值的位置。在这个位置可以读取和写入值。数据属性有4个描述其行为的特性;
configurable:表示能否通过delete删除属性从而重新定义属性,能否修改属性的特性,或者能否把属性修改为访问器属性。这个特性值默认为true。
enumerable:表示能否通过 for-in 循环返回属性。这个特性值默认为true。
writable:表示能否修改属性的值。这个特性值默认为true。
value: 包含这个属性的数据值。读取属性值的时候,从这个位置读;写入属性值的时候,把新值保存在这个位置上,这个特性值默认为undefined;
目前标准的浏览器支持这个方法,IE8-不支持此方法;
比如我们先定义一个对象person,如下:
var person = { name: 'longen' };
我们可以先alert(person.name); 打印弹出肯定是longen字符串;
理解writable属性;
现在我们使用Object.defineProperty()方法,对person这个对象的name属性值进行修改,代码如下: