[Node.js] 也说this
原文地址:http://www.moye.me/2014/11/21/也说this/
引子
Any sufficiently advanced technology is indistinguishable from magic.
老爷子所言不虚,各种技术里都有黑魔法,比如JavaScript,就有着像 this这样的奇葩存在。
What's this?
this是什么?大概能得到的答案有:
- 当前方法引用的对象实例
- 当前调用函数本身
- 全局上下文(顶层对象)
- 函数运行的context环境
哪种解释是对的呢?来看段代码:
function foo() {
console.log(this.a);
}
var a = 2;
var obj = {a: 1};
foo(); // 2 (在Node下是undefined)
foo.call(obj); // 1
obj.foo = foo;
obj.foo(); // 1
在这段代码中,this 呈现了三种可能:
- 全局上下文:foo执行时,this 开放式的指向了全局上下文(在node下为undefined,原因在于Global的作用域与浏览器不同
- 向方法传递的上下文:Function对象固有的apply或call方法,第一个参数均为 thisArg,它将被调用函数做为执行的上下文(在非strict模式,如果这个值为null或undefined,将有污染全局上下文的风险
- 方法引用的对象:可以将这个对象看成new创建的对象,函数的this将指向它
看起来是要有无限可能的节奏……好在我提前找到了这本书:
You Don't Know JS: this & Object Prototypes
To learn this, you first have to learn what this is not, despite any assumptions or misconceptions that may lead you down those paths. this is neither a reference to the function itself, nor is it a reference to the function’s lexical scope.
this is actually a binding that is made when a function is invoked, and what it references is determined entirely by the call-site where thefunction is called.
this 绑定上下文
this 实质上是一种绑定(binding)机制,只关乎函数被调用时所处的 上下文(context),而不关心它在哪里被定义。举个粟子:
function foo(something) {
this.a = something;
}
var obj1 = {
foo: foo
};
var obj2 = {};
obj1.foo( 2 );
console.log( obj1.a ); // 2
obj1.foo.call( obj2, 3 );
console.log( obj2.a ); // 3
var bar = new obj1.foo( 4 );
console.log( obj1.a ); // 2
console.log( bar.a ); // 4
this做为一个被绑定的context,甚至与函数依附的对象无关,通过obj1.foo.call( obj2, 3 )
一句我们能看清:这个context被引入,函数既可以读也可以修改它,但这里涉及到一个优先级问题,即:为什么 obj1绑定的this.a 没有被foo()改写,却是 obj2的 this.a?
this 绑定优先级
绑定 this 的形式大概有以下几种,它们的优先级如下排列:
- 被new过的函数实例,那么函数里的this绑定的就是这个实例对象本身,如
var bar = new foo();
- 函数是被 call 或者 apply 调用,那么 this 绑定的是第一个参数:
var bar = foo.call( obj2 );
- 函数是被某个对象引用的方法,那么它的this 绑定的是这个对象:
var bar = obj1.foo();
- 最后,就是隐式绑定了,这种情况的this 绑定的是全局上下文,在 strict mode(Node)下是 undefined:
var bar = foo();
建议
对于闭包惯用的self = this
技俩,You Don't Know JS 一书是不提倡的,它的建议是:
Embrace this-style mechanisms completely, including using bind(..) where necessary, and try to avoid self = this ...
Function.prototype.bind,它的实现看起来是这样的:
if (!Function.prototype.bind) {
Function.prototype.bind = function (oThis) {
if (typeof this !== "function") {
// closest thing possible to the ECMAScript 5
// internal IsCallable function
throw new TypeError(
"Function.prototype.bind - what is trying " +
"to be bound is not callable"
);
}
var aArgs = Array.prototype.slice.call(arguments, 1),
fToBind = this,
fNOP = function () {
},
fBound = function () {
return fToBind.apply(
(this instanceof fNOP && oThis ? this : oThis),
aArgs.concat(Array.prototype.slice.call(arguments))
)
};
fNOP.prototype = this.prototype;
fBound.prototype = new fNOP();
return fBound;
};
}
更多文章请移步我的blog新地址: http://www.moye.me/
[Node.js] 也说this的更多相关文章
- node.js学习(三)简单的node程序&&模块简单使用&&commonJS规范&&深入理解模块原理
一.一个简单的node程序 1.新建一个txt文件 2.修改后缀 修改之后会弹出这个,点击"是" 3.运行test.js 源文件 使用node.js运行之后的. 如果该路径下没有该 ...
- 利用Node.js的Net模块实现一个命令行多人聊天室
1.net模块基本API 要使用Node.js的net模块实现一个命令行聊天室,就必须先了解NET模块的API使用.NET模块API分为两大类:Server和Socket类.工厂方法. Server类 ...
- Node.js:进程、子进程与cluster多核处理模块
1.process对象 process对象就是处理与进程相关信息的全局对象,不需要require引用,且是EventEmitter的实例. 获取进程信息 process对象提供了很多的API来获取当前 ...
- Node.js:理解stream
Stream在node.js中是一个抽象的接口,基于EventEmitter,也是一种Buffer的高级封装,用来处理流数据.流模块便是提供各种API让我们可以很简单的使用Stream. 流分为四种类 ...
- Node.js:Buffer浅谈
Javascript在客户端对于unicode编码的数据操作支持非常友好,但是对二进制数据的处理就不尽人意.Node.js为了能够处理二进制数据或非unicode编码的数据,便设计了Buffer类,该 ...
- node.js学习(二)--Node.js控制台(REPL)&&Node.js的基础和语法
1.1.2 Node.js控制台(REPL) Node.js也有自己的虚拟的运行环境:REPL. 我们可以使用它来执行任何的Node.js或者javascript代码.还可以引入模块和使用文件系统. ...
- Node.js npm 详解
一.npm简介 安装npm请阅读我之前的文章Hello Node中npm安装那一部分,不过只介绍了linux平台,如果是其它平台,有前辈写了更加详细的介绍. npm的全称:Node Package M ...
- Node.js入门(一)
一.Node.js本质上是js的运行环境. 二.可以解析js代码(没有浏览器安全级的限制): 提供系统级的API:1.文件的读写 2.进程的管理 3.网络通信 三.可以关注的四个网站: 1.https ...
- Node.js学习笔记——Node.js开发Web后台服务
一.简介 Node.js 是一个基于Google Chrome V8 引擎的 JavaScript 运行环境.Node.js 使用了一个事件驱动.非阻塞式 I/O 的模型,使其轻量又高效.Node.j ...
- Node.js入门
开始之前,安利一本正在看的书<站在两个世界的边缘>,作者程浩,上帝丢给他太多理想,却忘了给他完成理想的时间.OK,有兴趣的可以看一看. node.js如标题一样,我也是刚开始接触,大家一起 ...
随机推荐
- fidder 抓 https包配置方法(ios & android & pc浏览器)
1. fidder抓https包的基本配置,可参见以下博文 http://blog.csdn.net/idlear/article/details/50999490 2. 遇到问题:抓包看只有Tunn ...
- isInstance和isAssignableFrom的用法
String str = ""; Object o = new Object(); System.out.println(String.class.isInstance(o)); ...
- linux上挂载windows共享文件夹
linux上挂载windows共享文件夹 1.共享windows目录 挂载之前得创建一个有password的用户(当前用户也能够),并将你要挂载的目录进行共享,并赋予读写权限 如图. watermar ...
- Xcode7 使用NSURLSession发送HTTP请求的问题
报错信息: Application Transport Security has blocked a cleartext HTTP (http://) resource load since it i ...
- 【LeetCode】338. Counting Bits (2 solutions)
Counting Bits Given a non negative integer number num. For every numbers i in the range 0 ≤ i ≤ num ...
- Raw-OS源代码分析之消息系统-Queue_Size
分析的内核版本号截止到2014-04-15.基于1.05正式版.blogs会及时跟进最新版本号的内核开发进度,若源代码凝视出现"???"字样,则是未深究理解部分. Raw-OS官方 ...
- C# WinForm 技巧八:界面开发之“WeifenLuo.WinFormsUI.Docking+OutLookBar” 使用
概述 最近几天一直在关注WinFrom方面的文章主要还是园子里伍华聪的博客,在看看我们自己写的项目差不忍赌啊,有想着提炼一下项目的公共部分,公共部分有分为 界面,类库两方面,今天主要是把界面 ...
- Android Studio开发入门-引用jar及so文件
作者:王先荣 最近初学安卓开发,因为以前从未用过JAVA,连基本的语法都要从头开始,所以不太顺利.在尝试使用百度语音识别引擎时遇到了如何引用jar及so文件的问题.在GOOGLE加多次尝试之后, ...
- spring mvc jsp运行不起来的问题
spring mvc已经处理成让jsp运行,即: <bean class="org.springframework.web.servlet.view.InternalResourceV ...
- c++算法应用 预备
章 C + +程序设计 大家好!现在我们将要开始一个穿越" 数据结构.算法和程序" 这个抽象世界的特殊旅程,以解决现实生活中的许多难题.在程序开发过程中通常需要做到如下两点:一是高 ...