this总结,mark一下:

Object中的this:

Object方法中的this,指向的就是该对象,即谁调用this就指向谁,与C#等服务器语言的思想比较一致。

 let
demo = {
name: "dqhan",
action: function () {
console.log(this); //{name: "dqhan", action: ƒ}
(function () {
console.log(this);//Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, frames: Window, …}
// "use strict";
// console.log(this);//undefined
})();
}
};
demo.action();

demo对象调用action,action中的this指向的就是demo,action内部的自执行函数this则指向的是window,严格模式下为undefined。可以写个深层次的demo来看下会不会影响this的指向

 let
demo = {
name: "dqhan",
action: function () {
console.log(this) //{name: "dqhan", action: ƒ, innerDemo: {…}}
},
innerDemo: {
name: 'innerDqhan',
action: function () {
console.log(this)//{name: "innerDqhan", action: ƒ}
}
}
};
demo.action();
demo.innerDemo.action();

事实证明不会影响this的指向,这种方式的定义以及调用不参与原型链,不涉及this指向改变的问题。

函数中的this:

匿名函数中,函数体内的this指向为window,严格模式下为undefined。

 function demo(){
console.log(this);//Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, frames: Window, …}
// "use strict"
// console.log(this);//undefined
}
demo();
 foo = 'outer'
function demo() {
this.foo = 'inner';
// "use strict";
// this.foo = 'inner';//error
}
console.log(foo);//outer
demo();
console.log(foo);//inner

foo在不加var,let(ES6)下自动挂载window下,调用demo后在函数内部将foo重新赋值。严格开发下this为undefined报错。

构造函数中的this:

提到this常常想到的是构造函数,写个简单的demo如下

 function Demo() {
this.name = "dqhan";
this.action = function () {
console.log(this)//Demo {name: "dqhan", action: ƒ}
};
}; let
demo = new Demo();
demo.action();
console.log(demo.name);//dqhan

调用demo内的action,action中的this指向构造函数的实例化对象,原因是什么呢?这里需要了解一下let demo = new demo();到底发生了什么。

 //action1
let
demo = new Demo();
//action2
let
demo = {};
demo.__proto__ = Demo.prototype;
Demo.call(demo);

js中new一个实例化对象的过程等价于action2的代码,最后一步通过call方法(apply,bind)将demo对象中的this传递到了Demo构造函数中,从而将构造函数中没有定义在原型中的属性与方法都定义到了demo 对象中,这就是为什么构造函数中的this会是实例化对象的原因。另外我们可以将属性或者方法都定义在原型中

 function Demo() {
this.name = "dqhan";
};
Demo.prototype.action = function () {
console.log(this)//Demo {name: "dqhan", action: ƒ}
}; let
demo = new Demo();
console.log(demo.name);//dqhan

我们都清楚,构造函数类似于一个简单工厂模式,我们可以通过一个构造函数生成很多其他对象,我们将属性或者方法定义在原型中,这样可以达到原型共享的目的。

 function Demo() {
this.name = "dqhan";
};
Demo.prototype.action = function () {
console.log(this)//Demo {name: "dqhan", action: ƒ}
};
let
demo = new Demo(),
demo1 = new Demo(),
demo2 = new Demo();
demo.__proto__ === demo1.__proto__;//true
demo1.__proto__ === demo2.__proto__;//true

当对象非常多的是时候,可以节约内存。

当函数内嵌套匿名函数

 function Demo() {
this.name = "dqhan";
};
Demo.prototype.action = function () {
console.log(this);//Demo {name: "dqhan", action: ƒ}
(function () {
console.log(this);//Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, frames: Window, …}
// "use strict";
// console.log(this)//undefined
})();
};
let
demo = new Demo();
demo.action();

定义在构造函数内的方法在传递的时候,实例化对象不会跟着一起传过去

 function Demo() {
this.name = "dqhan";
};
Demo.prototype.action = function () {
console.log(this); };
function foo(method){
method();
};
let
demo = new Demo();
foo(demo.action);//Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, frames: Window, …}
 function Demo() {
this.name = "dqhan";
};
Demo.prototype.action = function (method) {
console.log(this);
method();
};
Demo.prototype.actionCallBack = function () {
console.log(this);
}
let
demo = new Demo();
demo.action(demo.actionCallBack);
//Demo {name: "dqhan"}
//Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, frames: Window, …}

这两种情况都是将实例化对象中的方法当成参数进行传递。但是在执行函数中,this的上下文已经发生改变。解决方式可以通过bind,apply,call等改变上下文的方式。

 function Demo() {
this.name = "dqhan";
};
Demo.prototype.action = function (method) {
console.log(this);
method()
};
Demo.prototype.actionCallBack = function () {
console.log(this);
}
let
demo = new Demo();
demo.action(demo.actionCallBack.bind(demo));
// Demo {name: "dqhan"}
// Demo {name: "dqhan"}
 function Demo() {
this.name = "dqhan";
};
Demo.prototype.action = function () {
console.log(this);
(function () {
console.log(this);
}).apply(this);
};
let
demo = new Demo();
demo.action();
// Demo {name: "dqhan"}
// Demo {name: "dqhan"}

setTimeout中的延迟函数中this

 let
obj = {
timerAction: function () {
console.log(this);
}
};
function foo(method) {
method();
};
obj.timerAction();
foo(obj.timerAction);
setTimeout(obj.timerAction, 0);
// {timerAction: ƒ}
// Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, frames: Window, …}
// Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, frames: Window, …}

之前看过一篇关于setTimeout使用时延迟函数自动挂载window上。今天总结了一下,发现这种方式个人觉得可以理解成,以函数当做参数进行传递this都是传递不过去的。如果简单的写一个函数,那么问题就更不存在了,匿名函数本身就是挂载window下,没有争议了。

随机推荐

  1. 149. Best Time to Buy and Sell Stock【medium】

    Say you have an array for which the ith element is the price of a given stock on day i. If you were ...

  2. CEdit 控制键盘操作

    写在前面的话:在工作中要实现这样一个功能,在一个树形控件中选择要发送消息的客户,添加到一个列表控件中,点击确定跳到一个信息发送页面如下图,在发送人编辑框中显示选择的客户,要实现的就是即允许用户删除用户 ...

  3. PhantomJS与CasperJS在Windows下的安装与使用

    按照网上的教程来呢,一定是不好使的,这是常理. 所以必须要告诉你怎么使用Phantomjs…… 这么用! 1.下载Phantomjs的压缩包并解压缩: 2.在bin目录(包含phantomjs.exe ...

  4. jquery全部版本

    http://www.jb51.net/zt/jquerydown.htm 这个地方实时更新jquery版本

  5. Maven项目下HttpServletRequest 或 HttpServletResponse需引用的依赖包

    转载: http://xyly624.blog.51cto.com/842520/865630/ Maven项目下HttpServletRequest 或 HttpServletResponse需引用 ...

  6. iOS-打包成ipa的4种方法

    打包ipa的前提 1.证书的申请和设置和上面文章的一样 从第一步到第四步都是一样的http://www.cnblogs.com/sunfuyou/p/5900592.html2.还有第六步的 1-3都 ...

  7. CSS3和js炫酷点击按钮3D翻转动画特效

    简要教程 flipside是一款使用CSS3和js制作的炫酷点击按钮无缝过渡到确认面板的过渡动画特效.该点击按钮特效在按钮不同方向的边部点击时,产生的过渡动画特效是不一样的. 在线预览   源码下载 ...

  8. js获取相同name文本框的value

    <html xmlns="http://www.w3.org/1999/xhtml"><head runat="server"> < ...

  9. ExtJS获取Grid的行数

    1.     grid.getSelectionModel().getCount() ;  // 获得当前选中的行数  2.     grid.getStore().getTotalCount();  ...

  10. window上将MongoDB的启动加入到服务中

    在系统管理员的命令行模式中: 进入mongo的安装目录,参照如下: 其中: --dbpath为保存的数据的路径 mongod --bind_ip --serviceName "MongoDB ...