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下,没有争议了。
随机推荐
- 在Unity3D中连接WCF服务端
服务端不多讲解,有一处需要改的地方.具体服务端请看WCF入门学习2-控制台做为宿主 建议实际项目不要拿去用,毕竟是mono不是原生.net.或许是个坑 由于Unity的mono版本问题不能直接用net ...
- [na]数据包由于isp不稳定丢包-seq&ack
知识参考: http://www.xianren.org/net/wireshark-q.html 背景 总行wac管理分行ap.手机终端打不开portal页面. 2,分别抓包(portal页面从wa ...
- cocos2d-x 粒子动作 setTexture
CCSize s = CCDirector::sharedDirector()->getWinSize(); CCNode* explosion = CCParticleSun::create( ...
- 中文转Punycode
package cn.cnnic.ops.udf; public class GetPunycodeFromChinese { static int TMIN = 1; static int TMAX ...
- java 多线程11:volatile关键字
直接先举一个例子普通的线程实例变量的非可见性: public class MyThread28 extends Thread { private boolean isRunning = true; p ...
- mysql 存入乱码问题
在使用mysql开发是,遇到一问题,java脚本里面的中文很正常,持久化之后数据库里面的数据则变成乱码,解决方式,在spring配置文件连接中加入指定编码格式,有些系统不需要,有些服务器系统需要,统一 ...
- HOW TO:使用 Visual C# .NET 打印 RichTextBox 控件的内容
概要 本分步指南介绍了如何打印 RichTextBox 控件的内容.RichTextBox 控件没有提供任何打印 RichTextBox 内容的方法.您可以扩展 RichTextBox 类以使用 EM ...
- C语言 · 前10名
算法提高 前10名 时间限制:1.0s 内存限制:256.0MB 问题描述 数据很多,但我们经常只取前几名,比如奥运只取前3名.现在我们有n个数据,请按从大到小的顺序,输出前10个名 ...
- C中结构体的存储分配
C中结构体的存储分配 对于C语言中结构体所占的存储空间的大小,也一直是笔试面试的常客,今天好好看了一下这方面,以前一直以为很清楚了,今天通过各种实际测试举例,发现原来还是没有搞透彻,好在现在是彻底懂了 ...
- CSS样式表——布局练习(制作360网页)
以制作360网页为例(只做到了静态网页) 提纲:1.总共分为7部分 悬浮窗: 源代码: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Tra ...