this的工作原理

如果一个函数被作为一个对象的方法调用,那么this将被指派为这个对象。

var parent = {
    method: function () {
        console.log(this);
    }
};
 
parent.method();
// <- parent
 
注意这种行为非常“脆弱”,如果你获取一个方法的引用并且调用,那么this的值不会是parent了,而是window全局对象。这让大多数开发者迷惑。
var parentless = parent.method;
 
parentless();
// <- Window
 
底线是你应该查看调用链,以理解被调用函数是一个对象的属性还是它自己。如果它被作为属性调用,那么this的值将变成该属性的对象,否则this的值将被指派为全局对象或window。如果在严格模式下,this的值将是undefined。
 
在被当作构造函数的情况下,当使用new关键字时,this将被指派为被创建的实例对象。
 
function ThisClownCar () {
  console.log(this);
}
 
new ThisClownCar();
// <- ThisClownCar {}
 
注意,在这种情况下没有办法识别出一个函数是否应该被用作构造函数,因此省略new关键字导致this的结果将是全局对象,就像我们上面看到的没有用parent调用的例子。
 
ThisClownCar();
// <- Window
 

改动this

.call、 .apply .bind 方法用来操作调用函数的方式,帮我们定义this的值和传递给函数的参数值。

Function.prototype.call 可以有任意数量的参数,第一个参数被分配给this,剩下的被传递给调用函数。

Array.prototype.slice.call([1, 2, 3], 1, 2)
// <- [2]
 
Function.prototype.apply 的行为和.call类似,但它传递给函数的参数是一个数组,而不是任意参数。
 
String.prototype.split.apply('13.12.02', ['.'])
// <- ['13', '12', '02']
 
Function.prototype.bind 创建一个特殊的函数,该函数将永远使用传递给.bind的参数作为this的值,以及能够分配部分参数,创建原函数的珂里化(curride)版本。
 
var arr = [1, 2];
var add = Array.prototype.push.bind(arr, 3);
 
// effectively the same as arr.push(3)
add();
 
// effectively the same as arr.push(3, 4)
add(4);
 
console.log(arr);
// <- [1, 2, 3, 3, 4]
 

作用域链中的this

在下面的例子,this将无法在作用域链中保持不变。这是规则的缺陷,并且常常会给业余开发者带来困惑。

function scoping () {
  console.log(this);
 
  return function () {
    console.log(this);
  };
}
 
scoping()();
// <- Window
// <- Window
 
有一个常见的方法,创建一个局部变量保持对this的引用,并且在子作用域中不能有同命变量。子作用域中的同名变量将覆盖父作用域中对this的引用。http://www.cnblogs.com/sosoft/
 
function retaining () {
  var self = this;
 
  return function () {
    console.log(self);
  };
}
 
retaining()();
// <- Window
 
除非你真的想同时使用父作用域的this,以及当前this值,由于某些莫名其妙的原因,我更喜欢是使用的方法.bind函数。这可以用来将父作用域的this指定给子作用域。
 
function bound () {
  return function () {
    console.log(this);
  }.bind(this);
}
 
bound()();
// <- Window

解密 JavaScript 中的 this的更多相关文章

  1. Javascript中双等号(==)隐性转换机制 JS里charCodeAt()和fromCharCode()方法拓展应用:加密与解密

    Javascript中双等号(==)隐性转换机制   在Javascript中判断相等关系有双等号(==)和三等号(===)两种.其中双等号(==)是值相等,而三等号(===)是严格相等(值及类型是否 ...

  2. nodejs与javascript中的aes加密

    简介 1.aes加密简单来说,在密码学中又称Rijndael加密法,是美国联邦政府采用的一种区块加密标准.这个标准用来替代原先的DES,已经被多方分析且广为全世界所使用.高级加密标准已然成为对称密钥加 ...

  3. [转载]JavaScript 中小数和大整数的精度丢失

    标题: JavaScript 中小数和大整数的精度丢失作者: Demon链接: http://demon.tw/copy-paste/javascript-precision.html版权: 本博客的 ...

  4. javascript中的Array对象 —— 数组的合并、转换、迭代、排序、堆栈

    Array 是javascript中经常用到的数据类型.javascript 的数组其他语言中数组的最大的区别是其每个数组项都可以保存任何类型的数据.本文主要讨论javascript中数组的声明.转换 ...

  5. javascript中的this与函数讲解

    前言 javascript中没有块级作用域(es6以前),javascript中作用域分为函数作用域和全局作用域.并且,大家可以认为全局作用域其实就是Window函数的函数作用域,我们编写的js代码, ...

  6. JavaScript 中的数据类型

    Javascript中的数据类型有以下几种情况: 基本类型:string,number,boolean 特殊类型:undefined,null 引用类型:Object,Function,Date,Ar ...

  7. javascript中的操作符详解1

    好久没有写点什么了,根据博主的技术,仍然写一点javascript新手入门文章,接下来我们一起来探讨javascript的操作符. 一.前言 javascript中有许多操作符,但是许多初学者并不理解 ...

  8. 掌握javascript中的最基础数据结构-----数组

    这是一篇<数据结构与算法javascript描述>的读书笔记.主要梳理了关于数组的知识.部分内容及源码来自原作. 书中第一章介绍了如何配置javascript运行环境:javascript ...

  9. javascript中变量提升的理解

    网上找了两个经典的例子 var foo = 1; function bar() { if (!foo) { var foo = 10; } alert(foo); } bar(); // 10 var ...

随机推荐

  1. Angular实现递归指令 - Tree View

    在层次数据结构展示中,树是一种极其常见的展现方式.比如系统中目录结构.企业组织结构.电子商务产品分类都是常见的树形结构数据. 这里我们采用Angular的方式来实现这类常见的tree view结构. ...

  2. 修复Telerik reporting 在网页中使用时的样式

    在ASP.NET 网页或ASP MVC中嵌入Telerik Reporting时,报表出来的样式是有问题的,按扭的位置错位了. 在页面中引入以下CSS文件可以将报表样式修复从而回到正常的报表样式. . ...

  3. 分离EF connectionString里的db连接串

    创建EF模型后,自动生成的connectionString如下: <add name="TravelPPEntities" connectionString="me ...

  4. 我心中的核心组件(可插拔的AOP)~分布式Session组件

    回到目录 对于目前的网站来说,为了满足高可用,高并发,高负载,一台WEB服务器已经远远不够用了,以后的WEB应用服务器应该是一种集群的环境,它们之间使用一些工具进行数据的同步,在由1台变成多台服务器时 ...

  5. EF架构~为导航属性赋值时ToList()的替换方案

    回到目录 今天在进行EF开发时,遇到一个问题,在进行join查询时,类中的一个集合类型的导航属性,在给它赋值时,将查询出来的结果ToList()后,出错了,linq to entity不支持这种操作, ...

  6. Js~(function(){})匿名自执行方法的作用

    匿名自执行方法体(function(){})经常用在设计JS插件上面,它定义相关组件的行为,自动初始化相关属性,而且在页面中可以直接执行,你不需要手动执行它,它被自动被执行! 在设计你的匿名自执行方法 ...

  7. Node.js入门:文件查找机制

    文件查找流程图 从文件模块缓存中加载     尽管原生模块与文件模块的优先级不同,但是都不会优先于从文件模块的缓存中加载已经存在的模块. 从原生模块加载     原生模块的优先级仅次于文件模块缓存的优 ...

  8. lua随机数的问题

    在看 lua 的 math.random 函数的时候发现一个问题,就是在没有重新设置随机种子的时候, random 返回的前几个随机数并不是那么特别随机,尤其当随机范围很小的时候,比如 100 左右的 ...

  9. MSSQL Server数据库的四种连接方法和sql连接字符串

    MSSQL Server数据库的四种连接方法和sql连接字符串 分类: [ 03 ] C#(131) [ 07 ] SQL Server(68) [ 01 ] .NET(189) 今天用SQL Ser ...

  10. iOS-数据持久化-对象归档

    一.简单说明 对象归档是将对象归档以文件的形式保存到磁盘中(也称为序列化,持久化),使用的时候读取该文件的保存路径读取文件的内容(也称为接档,反序列化), (对象归档的文件是保密的,在磁盘上无法查看文 ...