上一篇随笔讲解了构造函数、原型及原型链相关的知识,今天让我们一起来探讨另一个问题:this。

一     this 的指向

  1,  函数预编译过程中,this指向window

  我们在讲解函数预编译过程的时候提到,函数在将要被执行时,会在[[scope]]属性中插入一个AO对象,AO对象包含了函数的形参、函数内声明的变量及子函数。实际上AO对象还有两个属性:this和arguments

  arguments用来存储接下来函数执行过程中接受到的实参列表。this用来接受函数中没有被声明就被赋值的变量(未声明访问将报错)。可以简单的理解为JavaScript的一种容错机制。这里的this就指向window,所以我们才说未声明的变量将被升级成window的属性。

 function test(a,b){
c = 10;
console.log(arguments);
console.log(c === window.c);
}
test(1,2);
//Arguments{0:1,1:2;length:2,...} 类数组
//true

  2,  全局作用域里this指向window。

  JavaScript的执行环境就是window,所以在全局作用域里window === this。

 console.log(this === window);//true

  3,  obj.method() 方法中的this指向obj

  如果有对象调用方法,那么方法内的this将指向调用对象。

  如果没有对象调用方法,即函数(方法)空执行,这里面的this还是将指向window。

 var name =  'ru';
var obj = {
name:'ren',
method:function(){
console.log(this.name);
}
};
obj.method();//'ren'
var test = obj.method;
test();//'ru'

二   call/apply/bind

  可以改变函数内部this的指向。

  1,  call(myThisarg,agr1,arg2,...)

  call()方法使用一个指定的对象替代函数内原本的this。函数原有的参数依次添加在其后。如果第一个参数是null或者undefined,那么函数内部的this将不被改变。

 function Person(name,age,sex){
this.name = name;
this.age = age;
this.sex = sex;
}
/*
function Student(name,age,sex,classes,num){
this.name = name;
this.age = age;
this.sex = sex;
this.classes = classes;
this.num = num;
}
这种写法当然能够实现我们的功能,但Student构造函数的功能完美涵盖了Person,我们是否可以在创建Student实例时调用Person以简化代码呢?当然
*/
function Student(name,age,sex,classes,num){
Person.call(this,name,age,sex);
this.classes = classes;
this.num = num;
}
var student = new Student(1,2,3,4,5);
console.log(student);//{name:1,age:2,sex:3,classes:4,num:5}
 var person = {
name : 'ren',
say : function(){
console.log(this.name);
}
};
var animal = {
name : 'dog'
};
person.say();//'ren'
animal.say();//Typerror:animal.say is not a function
//我们怎么才能让dog也能学ren一样说话呢?
person.say.call(animal);//'dog'

  2,  apply()

  apply()方法的功能和call()完全一样。只是apply以数组形式接受原函数的参数。

 var arr = [50,-1,-20,2,99,38];
//我们怎么拿到arr数组中最大或最小的那个数呢?你可能第一反应当然是数组的sort方法。但今天我们有一个使用更简单的方法!
Math.max.apply(null,arr);//
Math.min.apply(null,arr);//-20
//因为这里不涉及操作this的问题,所以第一个参数为null

  3,  bind()

  bind()方法使用方式和call()完全一样,但功能上有所差别。bind执行会返回一个函数,这个函数内部的this已被改变,等待在合适的时候被调用。

call和apply是在函数执行时改变其this的指向,而bind是先改变函数内的this指向,然后返回一个新的函数。

 var person = {
name : 'ren',
say : function (){
console.log(this.name);
}
};
var animal = {
name : 'dog'
};
person.say.call(animal);//'dog' 立即返回执行结果
var test = person.say.bind(animal); //返回一个函数
console.log(test);//fn
test();//'dog'

三     callee、caller

  1,callee

arguments的一个属性,指向函数本身。

一般用在立即执行函数的递归调用。因为立即执行函数会忽略函数名,所以在递归调用时可以用callee来解决。

 var factorial = (function(n){
if(n == 1){
return 1;
}else{
return n * arguments.callee(n - 1);
}
}(50));

  2,caller

函数的一个属性,指向执行时的父函数。全局执行时,fn.caller == null。好像并没有什么卵用?

  另外,这两个属性在严格模式下还不能使用。

四   ES5严格模式

  关于ES5的严格模式这里就不详细讲解了,有兴趣的同学可以去这里:

  https://www.cnblogs.com/snandy/p/3428171.html

最新文章

  1. Android中webView和网页的交互
  2. 三、jQuery--jQuery插件--jQuery插件——Validation Plugin
  3. Instuments工具
  4. 线下线上对接的一种思路(本地erp与线上电子商务平台对接)
  5. page resizing
  6. 项目回顾1-图片上传-form表单还是base64-前端图片压缩
  7. int *p()与int (*p)()的区别
  8. suibi 117
  9. QuickStart下的CommandFilter项目 github上自己修改过的版本
  10. Oracle 流式制造功能培训
  11. [Leetcode] Validate BST
  12. 【COGS1384】鱼儿仪仗队
  13. 设置CentOS开机连接网络 Centos 开机启动网卡的设置方法
  14. js jquery 实现html页面之间参数传递(单一参数、对象参数传递)
  15. gulp相关知识(2)
  16. 掌握这些知识,你的python水平能更上一层楼
  17. JavaScript夯实基础系列(一):词法作用域
  18. 【如皋OJ】1127:正整数N转换成一个二进制数
  19. Java实现单词树(trie)
  20. Nginx反向代理400错误

热门文章

  1. LoRaWAN stack移植笔记(六)_调试2
  2. Jupter NotebooK学习
  3. 谷歌移动UI框架Flutter教程之Widget
  4. 初学HTML5做的小知识点
  5. C#开发BIMFACE系列3 服务端API之获取应用访问凭证AccessToken
  6. JavaWeb实现增删查改(图书信息管理)——之查询
  7. electron-vue-webpack引入bootstrap多实例问题Multiple instances of Vue detected!
  8. 从入门到入土的JS 随笔day01
  9. 阿里云(ecs服务器)使用1-安装Mongdb数据库以及远程部署
  10. CodeForces 931E Game with String