this的定义:表示当前执行代码的环境对象
所以可将 this 的剖析分为“全局环境” 和 “函数环境” 两种类型的环境对象javascript
console.log(this === window); // true var a = 10; console.log(this.a); // 10
在函数内部,this 的取值取决于函数被调用时的运行环境。java
这里涉及到内存里的数据结构相关的知识点,当咱们定义如下字面量对象时会发生一系列的关联关系数据结构
var obj = { name: 'Tom' };
app
javascript 引擎会先在内存中生成 { name: 'Tom' } 对象,接着再把这个对象的内存地址赋值给 obj 变量,因此 obj 变量保存的只是一个内存地址而已,若是要获取 obj.name,javascript 引擎会先从 obj 变量中拿到内存地址,而后从该地址中获取原始对象,再返回 name 属性。函数
而属性值为函数时,该函数会被保存在内存中,而后将该内存地址赋值给该属性,所以该地址赋值给不一样环境执行时它的做用域是不同的,而 this 对象就是指向函数当前的执行环境对象,执行环境是会在 Event Loop(事件循环)过程当中变化的,所以 this 在函数环境下是属于运行时的。oop
var name = 'Tom'; var obj = { name: 'Iceberg', say: function() { console.log('my name is ' + this.name); }, sub: { say: function() { console.log('my name is ' + this.name); } } }; obj.say(); // my name is Iceberg obj.sub.say() // my name is undefined; var say = obj.say; say(); // my name is Tom;
上面的例子说明 obj.say() 执行环境为 obj 对象,而 obj.sub.say() 的执行环境倒是 obj.sub 对象,而对于 obj.sub 来讲并无 name 属性,所以为 undefined;而 var say = obj.say; 则表示将 say 方法的内存地址赋值给全局变量,所以从全局变量 name 中取值。this
接下来从 this 在函数环境下的不一样运用场景来剖析prototype
1.事件回调函数code
var handler = { nickname: 'anonymous', register: function() { console.log(this.nickname); } } $('#registerBtn').on('click', handler.register); // undefined
以上逻辑点击触发后输出的是 undefined,由于函数被当作事件触发的回调函数执行时,this 是指向该触发事件对应的元素,如要 this 仍然以 handler 对象为执行环境,则可以使用函数的 bind 方法进行执行环境对象的绑定操做。对象
$('#registerBtn').on('click', handler.register.bind(handler)); // anonymous
2.构造函数
要理解 this 在构造函数中的逻辑就要理清楚构造函数在实例化过程当中都发生了什么。
1. function A() { 2. this.name = 'Tom'; 3. this.age = 20; 4. } 5. var a = new A();
使用 new 命令实例化构造函数 A 的过程当中会发生如下流程:
1.建立一个空对象,做为将要返回的对象实例 2.将该空对象的原型指向构造函数的 prototype 属性 3.将该空对象赋值给构造函数内部的 this 关键字 4.执行构造函数内部代码 5.默认返回 this 对象(如 return 的为非对象类型,如数字 123,会被忽略进而默认 return this 对象) 6.由以上逻辑可知道 this 关键字在构造函数中表示的是其实例对象。
bind
1. function A() { 2. this.nickname = 'Tom'; 3. this.say = function() { 4. console.log(this.nickname); 5. } 6. } 7. var b = { nickname: 'John' }; 8. var a = new A(); 9. var say = a.say; 10. var say1 = a.say.bind(a); 11. var say2 = a.say.bind(b); 12. say(); // undefined 13. say1(); // Tom 14. say2(); // John
call&apply
1. function A() { 2. this.name = 'Tom'; 3. this.sayName = function(){ 4. console.log(this.name); 5. }; 6. } 8. function B() { 9. this.name = 'John'; 10. } 12. var a = new A(); 13. a.sayName.call(new B()); // John
总结:
1.在通常函数中使用this指全局对象window
2.做为对象方法使用时,this指向该对象
3.做为构造函数使用时,this指向new出的实例
4.apply或call使用时,此方法第一个参数为改变后的调用函数的对象,函数里this指第一个参数。
5.被当作事件触发的回调函数执行时,this 是指向该触发事件对应的元素
题外:手写一个new操做
//新建一个类 function Otaku(name, age) { this.name = name; this.age = age; //自身的属性 this.habit = 'pk'; } //给类的原型上添加属性和方法 Otaku.prototype.strength = 60; Otaku.prototype.sayYourName = function() { console.log('I am' + this.name); } //实例化一个person对象 const person = new Otaku('cty', 5000); person.sayYourName(); console.log(person);