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下,没有争议了。
随机推荐
- 4X4矩阵键盘扫描程序
4X4矩阵键盘扫描: 1. 4根行线的GIO均设为Output,根列线的GIO均设为Input: 2. 4根行线的GIO分别置为0111.1011.1101.1110,读逐一读取列线GIO的值,可确定 ...
- iptables控制较复杂案例
场景设定: 管理员:192.168.101.80 公司有三个部门: 工程部:192.168.2.21-192.168.2.20 软件部门:192.168.2.21-192.168.2.30 经理办公室 ...
- CCMotionStreak(一)
void MotionStreakTest1::onEnter() { MotionStreakTest::onEnter(); CCSize s = CCDirector::sharedDirect ...
- C++面向对象程序设计的一些知识点(1)
1.函数重载而不出错是有条件的: (1).这些函数位于同一域内,如同一类中.同一文件中. (2).这些同名函数具有不同的参数特征标(特征标是指形參的个数.类型.排列顺序等). 2.引用特性(与指针对比 ...
- pssh安装和使用
前提,安装了python.pssh安装下载pssh-2.2.2.tar.gztar zxvf pssh-2.2.2.tar.gzcd pssh-2.2.2python setup.py buildpy ...
- encoding/path可能引起无数奇怪的问题
例如如下代码: <%@ page language="java" contentType="text/html; charset=UTF-8" pageE ...
- dvwa 源码分析(三) --- config.inc.php分析
<?php # If you are having problems connecting to the MySQL database and all of the variables belo ...
- iOS 获取沙盒文件路径及 写入/删除 沙盒文件
出于安全考虑,iOS系统的沙盒机制规定每个应用都只能访问当前沙盒目录下面的文件(也有例外,比如系统通讯录能在用户授权的情况下被第三方应用访问),这个规则把iOS系统的封闭性展现的淋漓尽致. 一.沙盒中 ...
- dubbox-admin-2.8.4和dubbox-monitor安装
一.安装zookeeper 安装过程参照以前写的一篇博客http://www.cnblogs.com/520playboy/p/6235415.html 二.dubbox 1.准备工作下载dubbox ...
- 【C#】往按钮事件中传递自定义参数
情景:代码动态生成的按钮,需要自定义点击事件.但是生成的点击事件的参数是固定的,如何才能传入自定义的参数? Button btn = new Button() { Content = "这是 ...