前端面试

3-4、作用域和闭包this-代码示例

2017-11-06  本文已影响30人  留白_汉服vs插画

3-4、作用域和闭包this-代码示例

new的过程

使用new关键字调用函数(newClassA(…))的具体步骤:

1. 创建空对象;

var obj = {};

2. 设置新对象的constructor属性为构造函数的名称,设置新对象的__proto__属性指向构造函数的prototype对象;

obj.__proto__ = ClassA.prototype;

3. 使用新对象调用函数,函数中的this被指向新实例对象:

ClassA.call(obj);  //{}.构造函数();

4. 将初始化完毕的新对象地址,保存到等号左边的变量中

注意:若构造函数中返回this或返回值是基本类型(number、string、boolean、null、undefined)的值,则返回新实例对象;若返回值是引用类型的值,则实际返回值为这个引用类型。

var foo = "bar";

function test () {

this.foo = "foo";

}

new test();                    //test中的this指新对象,并未改变全局的foo属性

console.log(this.foo);            // "bar"

console.log(new test().foo);  // "foo";

对照下面,this作为构造函数使用的时候,指的是构造的函数f

作为对象属性使用的时候,指的是对象obj

作为普通函数执行的时候,指的是window

在JS中,这三者都是用来改变函数的this对象的指向的,他们有什么样的区别呢。

在说区别之前还是先总结一下三者的相似之处:

1、都是用来改变函数的this对象的指向的。也就是函数运行时上下文。

2、第一个参数都是this要指向的对象。

3、都可以利用后续参数传参。

apply和call都是为了改变某个函数运行时的上下文而存在的(就是为了改变函数内部this的指向);

如果使用apply或call方法,那么this指向他们的第一个参数,apply的第二个参数是一个参数数组,call的第二个及其以后的参数都是数组里面的元素,就是说要全部列举出来;

那么他们的区别在哪里的,先看一个例子。

var xw = {

name : "小王",

gender : "男",

age : 24,

say : function() {

alert(this.name + " , " + this.gender + " ,今年" + this.age);

}

}

var xh = {

name : "小红",

gender : "女",

age : 18

}

xw.say();

本身没什么好说的,显示的肯定是小王 , 男 , 今年24。

那么如何用xw的say方法来显示xh的数据呢。

对于call可以这样:

xw.say.call(xh);

复制代码

对于apply可以这样:

xw.say.apply(xh);

xw的say函数apply在xh上。

而对于bind来说需要这样:

xw.say.bind(xh)();

xw的say方法,绑定在xh上。

如果直接写xw.say.bind(xh)是不会有任何结果的,看到区别了吗?call和apply都是对函数的直接调用,而bind方法返回的仍然是一个函数,因此后面还需要()来进行调用才可以。

那么call和apply有什么区别呢?我们把例子稍微改写一下。

var xw = {

name : "小王",

gender : "男",

age : 24,

say : function(school,grade) {

alert(this.name + " , " + this.gender + " ,今年" + this.age + " ,在" + school + "上" + grade);

}

}

var xh = {

name : "小红",

gender : "女",

age : 18

}

复制代码

可以看到say方法多了两个参数,我们通过call/apply的参数进行传参。

对于call来说是这样的

xw.say.call(xh,"实验小学","六年级");

复制代码

而对于apply来说是这样的

xw.say.apply(xh,["实验小学","六年级郑州牛皮癣医院"]);

复制代码

看到区别了吗,call后面的参数与say方法中是一一对应的,而apply的第二个参数是一个数组,数组中的元素是和say方法中一一对应的,这就是两者最大的区别。

那么bind怎么传参呢?它可以像call那样传参。

xw.say.bind(xh,"实验小学","六年级")();

但是由于bind返回的仍然是一个函数,所以我们还可以在调用的时候再进行传参。

xw.say.bind(xh)("实验小学","六年级");

分析,fn1函数,执行在{x:100}上,后面需要的参数用逗号隔开。如果是用apply,要用[ ]形式。

bind绑定在fn2上之后,还要执行一次,才算绑定成功。

上一篇下一篇

猜你喜欢

热点阅读