关于new
首先回顾一下new关键字
var ch = new Fa();
等价于
var ch = {};
ch.__prototype__ = Fa.prototype;
Fa.call(ch);
本质上call的第一个参数可以理解传入了一个this,改变了整个上下文
本文事例
运行环境 nodejs v7.7.2
拿一段观察者模式的代码来看
//js文件
function Event() {
this.handlers = {};
}
Event.prototype.on = function(type, cb) {
//exception handler, need to code
if("undefined" == typeof this.handlers[type]) {
this.handlers[type] = [];
}
this.handlers[type].push(cb);
}
Event.prototype.emit = function(type) {
//exception handler, need to code
if(this.handlers[type]) {
let funs = this.handlers[type];
for(let idx in funs) {
let fun = funs[idx];
setTimeout(fun, 0);
}
}
}
let eve = new Event();
eve.on("add", () => {
console.log("add");
});
eve.on("del", () => {
console.log("del");
});
eve.emit("del");
eve.emit("add");
如果上述的prototype属性赋值,将匿名函数修改成箭头函数,那么就会出问题
这是因为箭头函数中this
是指向词法作用域,这里面是全局变量module的属性exports
,而不是对象eve
可以使用一下代码验证
function Event() {
this.handlers = {};
}
Event.prototype.on = (type, cb) => {
//++
console.log(this.wwww);
//exception handler, need to code
if("undefined" == typeof this.handlers[type]) {
this.handlers[type] = [];
}
this.handlers[type].push(cb);
}
Event.prototype.emit = (type) => {
//exception handler, need to code
if(this.handlers[type]) {
let funs = this.handlers[type];
for(let idx in funs) {
let fun = funs[idx];
setTimeout(fun, 0);
}
}
}
//++
this.wwww = "wwww";
console.log(this === exports);
let eve = new Event();
eve.on("add", () => {
console.log("add");
});
eve.on("del", () => {
console.log("del");
});
eve.emit("del");
eve.emit("add");
延伸
如下js代码
this.wwww = "wwww";
var a = function() {
console.log(this.wwww);
}
a();
function b() {
console.log(this.wwww);
}
b();
var c = () => console.log(this.wwww);
c();
使用nodejs命令执行如上代码的js文件,输出的是
undefined
undefined
wwww
但是在终端里(或者chrome浏览器中),输出的是
wwww
wwww
wwww
这是因为在终端里,this就是指向全局变量global
,故而在对象Global
上会添加上www
,a
, b
, c
等等属性,运行时会取到调用者global
wwww属性
在js文件,this指向的是exports
对象(属性),同时a
,b
,c
属性并列
如下图所示
也就是说c
使用了箭头函数,内部this
指向了词法作用域
(措辞可能不准确,这里指变量exports
),那么就可以找到属性wwww
可以使用如下js文件验证
function b() {
console.log(this === global);
console.log(this.wwww);
}
b();