this总结
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下,没有争议了。
随机推荐
- 关于XILINX芯片IO管脚的上拉电阻的疑问
XILINX的每个IO脚都有一个可选的可配上拉电阻功能,现在我在配置文件的UCF里使用了这个上拉电阻:语法如下:NET"I_key_data" LOC = " ...
- 什么是WMS系统 金蝶仓库条码管理WMS系统介绍
汉码盘点机-专注于傻瓜式的仓库条码管理系统,是当前出入库工作效率最高.数据最准确的仓库管理办法. "WMS,即q=%E4%BB%93%E5%BA%93%E7%AE%A1%E7%90%86%E ...
- CentOS 7.0 以后的几件事情
1.当最大化时隐藏标题栏 或者使用tweak tool 在字体中将标题栏字体设置为0...建议这个方法. 2.添加epel源 yum -y --nogpgcheck install http://do ...
- 深入理解Eureka - Eureka Client获取注册信息机制
深入理解Eureka - Eureka Client获取注册信息机 Eureka Client提供了定时获取注册信息的机制.Eureka Client获取注册信息的所有逻辑都在DiscoveryCli ...
- eclipse 项目中的java文件没有在WEB-INF目录下的classes中 生成相对应的编译后的类
1.首先确定project->Build Automatically是否勾选上: 2.执行完第一步之后测试一下看是否能编译,如果还是不能,则进行手动编译: 3,进入clean对话框,选择Cle ...
- 使用 esxtop 识别存储性能问题
可以使用交互式 esxtop 实用程序提供连接到 VMware ESX 主机的各种设备的 I/O 衡量指标. 使用 esxtop 配置监控 要监控每个 HBA 的存储性能,请执行以下操作: 通过在命令 ...
- HttpWebRequest类与HttpRequest类的区别
HttpRequest类的对象用于服务器端,获取客户端传来的请求的信息,包括HTTP报文传送过来的所有信息.而HttpWebRequest用于客户端,拼接请求的HTTP报文并发送等. HttpWebR ...
- 初始化git linux上传文件常见问题
SSH生成id_rsa, id_rsa.pub后,连接服务器却报: Agent admitted failure to sign using the key 错误. 解决方法: 在当前用户下执行命令: ...
- jsp报源码
刚在get的一个姿势.在参数后面加负号即爆出源码. w7oami 表哥解释道其原理如下: 1.用了@file_get_contents 函数 2.cdn 或者负载均衡 才导致爆出源码.
- Java并发编程()阻塞队列和生产者-消费者模式
阻塞队列提供了可阻塞的put和take方法,以及支持定时的offer和poll方法.如果队列已经满了,那么put方法将阻塞直到有空间可用:如果队列为空,那么take方法将会阻塞直到有元素可用.队列可以 ...