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. ModelSim+Synplify+Quartus的Alte

    [page_break] 本文适合初学者,源代码:mux4_to_1.v  工作内容: 1.设计一个多路选择器,利用ModelSimSE做功能仿真: 2.利用Synplify Pro进行综合,生成xx ...

  2. application , application pool., W3wp ,httpapplication, domain

    Hosting and Consuming WCF Services https://msdn.microsoft.com/en-us/library/bb332338.aspx http://www ...

  3. 使用自定义验证组件库扩展 Windows 窗体

    使用自定义验证组件库扩展 Windows 窗体             1(共 1)对本文的评价是有帮助 - 评价此主题                          发布日期 : 8/24/20 ...

  4. python 分别用python2和python3伪装浏览器爬取网页内容

    python网页抓取功能非常强大,使用urllib或者urllib2可以很轻松的抓取网页内容.但是很多时候我们要注意,可能很多网站都设置了防采集功能,不是那么轻松就能抓取到想要的内容. 今天我来分享下 ...

  5. iOS自定义组与组之间的距离以及视图

    iOS自定义组与组之间的距离以及视图 //头视图高度 - (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(N ...

  6. 我对C++的一些疑问

    我对C++的一些疑问,最近使用C++,总感觉有些东西自己没有抓住,也可能是自己基础学的不是很扎实,所以对一些基本的东西理解不够透彻导致的.因为自己在学校也学过C#和java,C#它是一个完全的面向对象 ...

  7. python 字符串 大小写转换 以及一系列字符串操作技巧

    总结 capitalize() 首字母大写,其余全部小写 upper() 全转换成大写 lower() 全转换成小写 title() 标题首字大写,如"i love python" ...

  8. web开发,让用户流水线进行操作,不可返回后退

    在项目开发中非常多人会有这种需求.就是想要操作做过了不能后退.之前在网上找过点,都说没有什么好的办法.我有的说有js,但效果不好,不说连点两下能够让他失效,有不同浏览器中也无法兼容,如 functio ...

  9. gsm at 指令

    一.一般命令 AT+CGMI 给出模块厂商的标识. SONY ERICSSON AT+CGMM 获得模块标识.这个命令用来得到支持的频带(GSM900,DCS1800或PCS1900).当模块有多频带 ...

  10. Spring事务处理时自我调用的解决方案 嵌套AOP

    开涛的解决方案1 http://jinnianshilongnian.iteye.com/blog/1487235 AopContext.currentProxy() 原理 http://books. ...