一、new function的用法

1.用法一

此种用法的跟使用{}的区别是:它比较灵活,可以在内部定义变量、函数等

var obj = new function(){
   var a = 1; 
   var b = 2;
   this.total = a + b;
   return a + b; // 被忽略
}

相当于:

 var obj = {
   total : 3
 }

2.用法二

此种用法就是闭包而已

var test = new function(){

   var a = 1;
   var b = 2;

   return function(c){
      return a + b + c;
   }

}

test(3);//6

相当于:

var test = (function(){

   var a = 1;
   var b = 2;

   return function(c){
      return a + b + c;
   }

})();

test(3);//6

二、Function.prototype.apply.call的用法

function log(){
   if(window.console){
         // 第一个参数是apply要执行的函数,第二个参数为context,第三个参数为要执行函数的参数列表
         Function.prototype.apply.call(console.log,console,arguments);
         // Function.apply.call(console.log,console,arguments); // 也是可以的。
   }
}

三、构造函数中return

1.构造函数return基本类型的值

function Person(){

   var a = 2;

   this.a = a;

   return a;

}

var p = new Person();

console.dir(p); // 此时p的值并不是2,而是一个有一个属性a其值为2的对象

2.构造函数return Object类型的值

function Person(){

    var a = 2

    return {

       name:"李彦峰",
       a : a

    }

}
var p = new Person();

console.dir(p); // 此时p为一个对象 {name:"李彦峰",a:2}

结论:

  1. 在构造器中 return ,如果是基本类型的值,那么使用 new 操作符将会按照预期,返回一个对象,就相当于构造函数中的 return 语句不存在一样

  2. 在构造器中如果 return 的是一个Object类型(function/基本类型的包装类型/Object类型),那么 new 操作符就相当于不存在一样,也就是说,js引擎会把 return 出去的引用值作为变量,而不会把 new 出来的新对象的引用赋值给相应的变量。。

四、函数的属性

  • 函数的属性列表

    1. arguments

    2. caller

    3. length

    4. name

    5. prototype(这个属性先略过)

上述的属性都可以通过 函数名.属性来引用,length是形参的个数。如果是函数表达式的话,name是空串。


function outer(a,b,c){
    console.log(outer.arguments); // [1,2,3,4]
    console.log(outer.caller); // null
    console.log(outer.length); // 3
    console.log(outer.name); // outer
    function inner(){
        console.log(inner.arguments); // []
        console.log(inner.caller); // 打印出整个函数体
        console.log(inner.length); // 0
        console.log(inner.name); // inner
 
        // 内部函数访问外部函数的属性    
        console.log(arguments.callee.caller.arguments); // [1,2,3,4]
        // console.log(inner.caller.arguments);  // [1,2,3,4]
        console.log(arguments.callee.caller.caller); // null
        // console.log(inner.caller.caller); // null
        console.log(arguments.callee.caller.length); // 3
        // console.log(inner.caller.length); // 3
        console.log(arguments.callee.caller.name); // outer
        // console.log(inner.caller.name); // outer
    }
    inner();
}
outer(1,2,3,4);

五、局部变量

对于局部声明的重复变量,只有第一个声明有效,也就是说,js引擎会忽略除了第一个之外的所有的声明

 
 // 第一种
 function test(){
   
     var name = "李彦峰";
     var name; 
     console.log(name); // 李彦峰

 }

 // 第二种
 function test(){
    
     var name;
     var name = "李彦峰";
     console.log(name); // 李彦峰
    
 }

注意:第二种好像不符合 对于局部声明的重复变量,只有第一个声明有效的说法,其实也是符合的,因为js引擎会对函数进行2轮处理,局部变量的声明在第1轮处理(变量声明提升),所以第1轮会保证只有一个name被声明,第2轮才进行局部变量的初始化(代码执行到赋值语句才进行初始化),即会把第1轮声明的局部变量赋值。。

严格模式下不能通过函数名.arguments的方式访问arguments对象,不能访问caller属性

六、arguments

arguments对象拥有一个callee属性,该属性是一个指针,指向拥有这个arguments对象的函数

arguments对象内部属性值是跟参数一一对应的,改变其中一个的值都会影响另外一个。

看代码:


function test(a,b,c){
    console.log(arguments); // [1,2,4]
    a = 8;
    console.log(arguments); // [8,2,4]
    arguments[1] = 909;
    console.log(b); // 909
    console.log(arguments); // [8,909,4]
}
test(1,2,4);

注意:严格模式下不能访问arguments对象的callee属性


pod2g
1.2k 声望13 粉丝

前端之渣!