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下,没有争议了。
随机推荐
- jQuery attr方法修改onclick值
了通过jQuery的attr修改onclick值. 代码: var js = "alert('B:' + this.id); return false;"; var newclic ...
- jquery中选择块并改变属性值的方法
本文为大家介绍下使用jquery改变class属性的值,通过removeClass.addClass实现,具体如下,感兴趣的朋友可以学习下jquery改变class属性的值 $("#top_ ...
- 深入了解MySQL的索引
(一)关于存储引擎 创建合适的索引是SQL性能调优中最重要的技术之一.在学习创建索引之前,要先了解MySql的架构细节,包括在硬盘上面如何组织的,索引和内存用法和操作方式,以及存储引擎的差异如何影 ...
- vue的数组如何存储数据
vue 和 angular 还有有些区别的, 比如,vue中的数组数据改变后,view并没有发生改变,angular就不会这样. 所以VUE 在数组扩展方法中提供以了一个新的API arr.$set( ...
- pre 强制换行
当前位置:懒人建站 > javascript > 网页特效 > css强制pre标签换行 css强制pre标签换行,pre标签的功能就是保留文本源格式,将会保留文本的长度,空格 空行 ...
- css3实现jquery mobile的页面过度原理
1.两个页面在同一个html中用js点击实现另外一个页面增加ui-page-active slid in等各种效果,每个页面中是一个绝对定位 .ui-mobile [data-role=page] { ...
- css3实现立方体效果
<!DOCTYPE html><html><head><meta charset="utf-8" /><title>&l ...
- Linux作为路由器(一)
前言:Linux主机可以作为路由器使用,利用路由转发功能实现不同网络内的主机能够相互通信,利用iptables的SNAT功能来实现企业内网主机访问互联网,下面做个小的实验. 实验环境:VM (1)路由 ...
- Android——监听事件OnLongClickListener
.xml <Button android:layout_width="wrap_content" android:layout_height="wrap_conte ...
- C++ 递归实现汉诺塔
C++实现汉诺塔 #include <iostream> using namespace std; void move(int n,char x,char y,char z) { ) { ...