javascript中this那些事

定义

this是函数执行的上下文。数组

调用方式

1. 做为函数调用,指向window(严格模式报undefined的错)。bash

var name='hello';
function a() {    
    console.log(this.name)   
}
a();     //hello

var c={    
    name:'haha',    
    d: function(){ 
       a(); 
    } 
}
c.d();    //hello
复制代码

2. 做为属性调用,指向该对象。app

var name='hello';
function a(){   
    console.log(this.name)
}
var b={    
    name:'world',    
    a:a    
}
b.a();    //world
复制代码

有个陷阱,做为函数别名调用时,会丢失this。函数

var name='hello';
function a(){   
    console.log(this.name)
}
var b={    
    name:'world',    
    a:a    
}

var test=b.a;
test();     //hello
复制代码

3. 做为构造函数调用,会把属性挂到new出来的实例上。测试

function A(){    
    this.name='xiaoming'
}
var a=new A();
console.log(a.name);    //xiaoming
复制代码

若是构造函数有return,且return对象(包括{}、[]),那么new的实例就是return的值.ui

function A(){    
    this.name='xiaoming';
    return {}  
}
var a=new A();
console.log(a.name)    //undefined
复制代码

若是return的是字符串、“”、null、undefined,new的实例和无return时new的实例同样。this

function A(){    
    this.name='xiaoming';
    return null
}
var a=new A();
console.log(a.name);    //xiaoming
复制代码

其实new作了三件事:spa

  1. 建立一个新对象:var obj={}prototype

  2. 将obj的__proto__指向A.prototype:obj.__proto__=A.prototype;该步骤是为了继承构造函数A原型链。code

  3. 将this指向该新对象执行A:A.call(obj)

function Animal(){    
    this.animal="animal";
}
Animal.prototype.name="9"; //Animal构造函数原型的属性name
function Dog(){    
    this.dog="dog";    
}
Dog.prototype.__proto__=Animal.prototype;

var d=new Dog();
var obj={};
obj.__proto__=Dog.prototype;
Dog.call(obj);
复制代码

上面的例子中,对象d和对象obj彻底同样,结果都是下图的实例,都能访问Animal构造函数原型的属性name和方法。

改变this指向的三种方式

1.call

使用:Function.call(obj,arg0,arg1...)

将Function的this指向obj,第一个参数是this指向,后面的参数是传入Function的参数,通常用于参数个数固定的的函数。对于改变this指向,我我的理解是把函数里全部用到this的地方替换为obj。

2.apply

使用:Function.apply(obj,[arg0,arg1...])

将Function的this指向obj,第一个参数是this指向,第二个参数是传入Function的参数组成的数组,通常用于参数个数不固定的的函数。

3.bind

使用:Funtion(arg0,arg1...).bind(obj)

误区

误区1:this指向函数自己?

var name='hello'
function a(){    
    console.log(this.name);    
}
a.name='world';
a() ;    //打印hello
console.log(a.name)     //world
复制代码

题外话:

Object和Function既是对象,又是函数,二者内部同时含有proto和prototype属性。 Function.prototype指向”内置函数“。而Object.prototype指向”根源对象“

Object.__proto__ === Function.prototype //true
Object.__proto__ === Function.__proto__//true
Object.prototype === Function.prototype.__proto__ // true
//所以
Function instanceof Object //true
Object instanceof Function //true
复制代码

函数a的原型:

全部的函数都继承自 Object,函数的原型是Object的实例, 由于 Function.__proto__.__proto__===Object.prototype为true,也能够用 Function.prototype.isPrototypeOf(Object)为true判断。
是对象就能够增长属性,因此a.name挂在了函数上,那他有没有丢呢?由例子打印的第二个值能够看出来没丢。

是对象均可以增长属性,Array.__proto__.__proto__===Object.prototype为ture,Object.prototype.isPrototypeOf(Array.prototype)为true,因此Array和Function同样,也能够增长属性。感兴趣可自行测试。

误区2:this是函数局部做用域?

var name='hello'
function a(){  
    var name='world';  
    console.log(this.name)  
}
a();    //hello
复制代码

上例打印hello,不是world,说明this并非函数的局部做用域。

误区3:this指向父级函数做用域?

var name='hello'
function a(){  
    console.log(this.name) 
}
function b(){ 
    var name='world';    
    a();   
}
b();    //hello
复制代码

该例子打印的是hello,而不是world,说明this并非父级函数做用域,而是调用上下文。

误区4:函数的this指向与调用该函数的地方this相同?

var name='hello';
function a(){   
    console.log(this.name)
}
var c={    
    name:'haha',    
    d: function(){ 
        console.log(this.name); // haha 
        a(); 
    } 
}
c.d();    // haha  hello
复制代码

照理说,若是函数的this指向与调用该函数的地方this相同,那么两个都打印haha,然而事实倒是,先打印haha,再打印hello,说明跟调用函数外部的this无关,可能有人有困惑,为何会这样呢?我也不知道哈哈

相关文章
相关标签/搜索