call和apply的区别

昨天和js大神谈js,他说要是他出题的话,就问apply和call的区别。。。

现在整理一下,首先说apply和call的不同之处其实就是 方法传递的参数不同,(还有一个是性能方面的差别,apply的性能要差很多。)

call( fun, arg1 , arg2 ,arg3...... ), 而apply只接受 两个参数 apply( fun , [ arg1 , arg2 ,arg3....])(以数组形式存储)

两者的作用呢,都是变化上下文,所谓的上下文是指 对象的空间:

var a = {
    o : 100,
    m : function (){
     console.log(this.o);
     var o = 200;
       }
    }    

  则变量o和函数m的上下文就是对象 a。

注 :在JavaScript中,代码将总是有着某种形式的上下文(代码在其内部工作的 对象)

上下文是通过变量this(号称魔法变量)工作。变量this总是引用代 码当前所在的那个对象。记住全局对象实际上是window对象的属性。这意味着即使是在全局上下文里,this 变量仍然引用一个对象。

下面来举一些有点磨人的例子:

(1)全局变量k

var k = 200;
var obj = {
    f : function() {
        console.log( k );
        k = 100;
    }
        
}

obj.f();    // 200 ,k为一个全局的变量,k的上下文是window

(2 ) this.k,此处的this指代的对象是 obj,而在执行console.log(this.k)的时候,下一句k还没有定义,但是由于声明提前,所以k已经声明,所以不会报错,

而是undefined(相当于在内存开了一个0字节的内存,也就是只是声明了一个变量,而没有给它赋值,则默认值)

var k = 200;
var obj = {
    f : function() {
        console.log( this.k );
        k = 100;
    }
        
}

obj.f();   // undefined

(3) 自执行的函数,是一个自我封闭的区域,其中的this没有上下文,没有上下文默认为全局的window是其上下文。

var k = 200;
var o = {
    k : 100,
    m : (function()  {
     console.log(k);        //200
     console.log(this.k);   // 200
    } )()
}

o.m;

其他一些问题:(好难)

1.考的是函数中参数arguments的类型,arguments是参数的集合,是一个对象不是数组

(function(){
    return typeof arguments;
})()
结果是: object

2.命名函数表达式的函数名只对函数体内可见

var f = function g(){ return 23; };
  typeof g();
//根据标准,命名函数表达式的函数名只对函数体内可见
//因此报错

//Uncaught ReferenceError: g is not defined
//at <anonymous>:3:3
//at Object.InjectedScript._evaluateOn (<anonymous>:905:140)
//at Object.InjectedScript._evaluateAndWrap (<anonymous>:838:34)
//at Object.InjectedScript.evaluate (<anonymous>:694:21)

3.参数是不可删除的

(function(x){
    delete x;
    return x;
    })(1);
结果是:1

4.未赋值的变量默认为undefined

var y = 1, x = y = typeof x;
    x;
结果是:undefined
//声明两个变量x与y,y最初赋为1,x没有赋值,默认赋给window的一个属性undefined,
//因此typeof undefined为"undefined",最后x= y= "undefined"

5.函数名被优先级更高的参数名覆盖了,内存覆盖了

 (function f(f){
    return typeof f();
    })(function(){ return 1; });
//结果就是: typeof 1; 最终结果是: number
//函数名被优先级更高的参数名覆盖了

6.自执行函数的上下文,这个解释了自执行函数的上写文是window了

 var foo = { 
      bar: function() { return this.baz; }, 
      baz: 1
    };
    (function(){ 
      return typeof arguments[0]();
    })(foo.bar);
结果是: undefined
//我们把下面那个自动执行函数分解一下
//var a = function(){
//  return typeof arguments[0]();
//};
//a(foo.bar)
//执行完arguments[0](),即得到this.baz
//由于this变量在此绑定失效,它指向window,window有bax变量吗?
//没有,返回"undefined"

7.还是this指代的当前对象的变化

var foo = {
      bar: function(){ return this.baz; },
      baz: 1
    }
    typeof (f = foo.bar)();
结果是: undefined
解释是:这个函数可以等价于:
// window.f;
// f = foo.bar;
// f();
//此时this指向的对象是window了,所以最后结果是undefined;

8.内存中后赋值的会覆盖掉先赋值的(包括变量赋值和函数赋值哟)

 var f = (function f(){ return "1"; }, function g(){ return 2; })();
    typeof f;
结果是 typeof 2 => number
解释是: var a = ( 1,2,3 )
a ; => 3
函数赋值亦是这样,f先是赋值为f(),然后赋值为g().
所以最后执行的是g函数

9.这题好难。。。。理解

var x = 1;
 if (function f(){}) {
   x += typeof f;
 }
x ;
结果是: 1undefined
//函数声明只能裸露于全局作用域下或位于函数体中
//从句法上讲,它们不能出现在快中,例如不能出现在if,while,或for语句中,因为块只能包含语句。
因此if()中的f函数不能当做函数声明,当成表达式使用
//可能是预编译阶段做了如下处理:
//if ( xxx = function(){} )
//根据第2条,命名函数表达式的函数名只对函数体内可见,所以是找不到f的。

10.typeof undefined = "undefined" //string型的

  var x = [typeof x, typeof y][1];
     typeof typeof x;
结果是: string
x数组其实是: [ "undefined" , "undefined" ]

11.这题其实简单,就是要看清楚{有几层

 (function(foo){
      return typeof foo.bar;
    })({ foo: { bar: 1 } });
结果是: undefined
看到这样复杂的可以这样解释:
var a = {foo:{bar:1}}
(function( foo ) {
return typeof foo.bar
})(a);
a中的属性只有foo

12.声明提升

(function f(){
      function f(){ return 1; }
      return f();
      function f(){ return 2; }
    })();
结果: 2

13.这题就不是很明白,应该是instanceof对象是否是特定类的一个实例

function f(){ return f; }
 new f() instanceof f;
结果是:false
解释是: 由于函数f会返回自身,这个new就形同虚设
如果f的形式为function f(){ return this;}或function f(){}就不一样

14.函数的length就是指它形参的长度,with就是一个读写器,题意就是取出函数的length属性

with (function(x, undefined){}) length;
结果是:2

  

  

  

  

  

  

  

  

  

  

  

  

  

 

原文地址:https://www.cnblogs.com/shixiaomiao/p/4762820.html