JavaScript的this学习笔记
2017-11-13 23:19
603 查看
1 浏览器宿主的全局环境中,this指的是window对象
2 浏览器中在全局环境下,使用var声明变量其实就是赋值给this或window
3 任何情况下,创建变量时没有使用var或者let(ECMAScript 6),也是在操作全局this
4 除了DOM的事件回调或者提供了执行上下文的情况,函数正常被调用(不带new)时,里面的this指向的是全局作用域
5 当用调用函数时使用了new关键字,此刻this指代一个新的上下文,不再指向全局this
6 当通过new的方式创建了多个实例后,他们会共用一个原型,直到this.xxx被重写
7 在实例中,this是个特殊的对象,而this自身其实只是个关键字。可以把this想象成在实例中获取原型值的一种途径,同时对this赋值又会覆盖原型上的值。完全可以将新增的值从原型中删除从而将原型还原为初始状态
8 不通过实例,直接操作函数的原型
9 同一函数创建的所有实例均共享一个原型。如果给原型赋值了一个数组,那么所有实例都能获取到这个数组。除非你在某个实例中对其进行了重写,实际上是进行了覆盖
通常上面的做法是不正确的(改变thing1的同时也影响了thing2)。如果想每个实例互不影响,那么在函数里创建这些值,而不是在原型上。
10 多个函数可以形成原型链,这样this便会在原型链上逐步往上找直到找到想引用的值
注意原型链底层函数中对this的操作会覆盖上层的值
11 原型链方法中的this是从实例中的this开始住上查找整个原型链的。也就是说,如果原型链中某个地方直接对this进行赋值覆盖了某个变量,那么我们拿到 的是覆盖后的值。
12 在JavaScript中,函数可以嵌套函数,也就是可以在函数里面继续定义函数。但内层函数是通过闭包获取外层函数里定义的变量值的,而不是直接继承this
13 但把实例的方法作为参数传递时,实例是不会跟着过去的。也就是说,此时方法中的this在调用时指向的是全局this
解决方法就是传递的时候使用bind方法显示指明上下文,bind方法是所有函数或方法都具有的
同时也可以使用apply或call 来调用该方法或函数,让它在一个新的上下文中执行。
14 使用bind可以任意改变函数或方法的执行上下文,即使它没有被绑定到一个实例的原型上
15 对象中的this
可以在对象的任何方法中使用this来访问该对象的属性。这与用new得到的实例是不一样的
通过this所拿到的只是该对象身上的属性而已
也可以不通过this,直接访问对象的属性
2 浏览器中在全局环境下,使用var声明变量其实就是赋值给this或window
3 任何情况下,创建变量时没有使用var或者let(ECMAScript 6),也是在操作全局this
foo = "bar"; function testThis() { foo = "foo"; } console.log(this.foo); //logs "bar" testThis(); console.log(this.foo); //logs "foo"
4 除了DOM的事件回调或者提供了执行上下文的情况,函数正常被调用(不带new)时,里面的this指向的是全局作用域
foo = "bar"; function testThis() { this.foo = "foo"; } console.log(this.foo); //logs "bar" testThis(); console.log(this.foo); //logs "foo"
5 当用调用函数时使用了new关键字,此刻this指代一个新的上下文,不再指向全局this
foo = "bar"; function testThis() { this.foo = "foo"; } console.log(this.foo); //logs "bar" new testThis(); console.log(this.foo); //logs "bar" console.log(new testThis().foo); //logs "foo"
6 当通过new的方式创建了多个实例后,他们会共用一个原型,直到this.xxx被重写
function Thing() { } Thing.prototype.foo = "bar"; Thing.prototype.logFoo = function () { console.log(this.foo); } Thing.prototype.setFoo = function (newFoo) { this.foo = newFoo; } var thing1 = new Thing(); var thing2 = new Thing(); thing1.logFoo(); //logs "bar" thing2.logFoo(); //logs "bar" thing1.setFoo("foo"); thing1.logFoo(); //logs "foo"; thing2.logFoo(); //logs "bar"; thing2.foo = "foobar"; thing1.logFoo(); //logs "foo"; thing2.logFoo(); //logs "foobar";
7 在实例中,this是个特殊的对象,而this自身其实只是个关键字。可以把this想象成在实例中获取原型值的一种途径,同时对this赋值又会覆盖原型上的值。完全可以将新增的值从原型中删除从而将原型还原为初始状态
function Thing() { } Thing.prototype.foo = "bar"; Thing.prototype.logFoo = function () { console.log(this.foo); } Thing.prototype.setFoo = function (newFoo) { this.foo = newFoo; } Thing.prototype.deleteFoo = function () { delete this.foo; } var thing = new Thing(); thing.setFoo("foo"); thing.logFoo(); //logs "foo"; thing.deleteFoo(); thing.logFoo(); //logs "bar";
8 不通过实例,直接操作函数的原型
function Thing() { } Thing.prototype.foo = "bar"; Thing.prototype.logFoo = function () { console.log(this.foo, Thing.prototype.foo); } var thing = new Thing(); thing.foo = "foo"; thing.logFoo(); //logs "foo bar"; this是获取原型值的一个途径 改变的是值的指向而没有直接改变了值
9 同一函数创建的所有实例均共享一个原型。如果给原型赋值了一个数组,那么所有实例都能获取到这个数组。除非你在某个实例中对其进行了重写,实际上是进行了覆盖
function Thing() { } Thing.prototype.things = []; var thing1 = new Thing(); var thing2 = new Thing(); thing1.things.push("foo"); console.log(thing2.things); //logs ["foo"]
通常上面的做法是不正确的(改变thing1的同时也影响了thing2)。如果想每个实例互不影响,那么在函数里创建这些值,而不是在原型上。
function Thing() { this.things = []; } var thing1 = new Thing(); var thing2 = new Thing(); thing1.things.push("foo"); console.log(thing1.things); //logs ["foo"] console.log(thing2.things); //logs []
10 多个函数可以形成原型链,这样this便会在原型链上逐步往上找直到找到想引用的值
function Thing1() { } Thing1.prototype.foo = "bar"; function Thing2() { } Thing2.prototype = new Thing1(); var thing = new Thing2(); console.log(thing.foo); //logs "bar"
注意原型链底层函数中对this的操作会覆盖上层的值
function Thing1() { } Thing1.prototype.foo = "bar"; function Thing2() { this.foo = "foo"; } Thing2.prototype = new Thing1(); function Thing3() { } Thing3.prototype = new Thing2(); var thing = new Thing3(); console.log(thing.foo); //logs "foo"
11 原型链方法中的this是从实例中的this开始住上查找整个原型链的。也就是说,如果原型链中某个地方直接对this进行赋值覆盖了某个变量,那么我们拿到 的是覆盖后的值。
function Thing1() { } Thing1.prototype.foo = "bar"; Thing1.prototype.logFoo = function () { console.log(this.foo); } function Thing2() { this.foo = "foo"; } Thing2.prototype = new Thing1(); var thing = new Thing2(); thing.logFoo(); //logs "foo";
12 在JavaScript中,函数可以嵌套函数,也就是可以在函数里面继续定义函数。但内层函数是通过闭包获取外层函数里定义的变量值的,而不是直接继承this
function Thing() { } Thing.prototype.foo = "bar"; Thing.prototype.logFoo = function () { var info = "attempting to log this.foo:"; function doIt() { console.log(info, this.foo); } doIt(); } var thing = new Thing(); thing.logFoo(); //logs "attempting to log this.foo: undefined" //将this缓存起来,用个叫self或者其他什么的变量来保存,以将外层与内层的this区分开来 function Thing() { } Thing.prototype.foo = "bar"; Thing.prototype.logFoo = function () { var self = this; var info = "attempting to log this.foo:"; function doIt() { console.log(info, self.foo); } doIt(); } var thing = new Thing(); thing.logFoo(); //logs "attempting to log this.foo: bar"
13 但把实例的方法作为参数传递时,实例是不会跟着过去的。也就是说,此时方法中的this在调用时指向的是全局this
function Thing() { } Thing.prototype.foo = "bar"; Thing.prototype.logFoo = function () { console.log(this.foo); } function doIt(method) { method(); } var thing = new Thing(); thing.logFoo(); //logs "bar" doIt(thing.logFoo); //logs undefined
解决方法就是传递的时候使用bind方法显示指明上下文,bind方法是所有函数或方法都具有的
function Thing() { } Thing.prototype.foo = "bar"; Thing.prototype.logFoo = function () { console.log(this.foo); } function doIt(method) { method(); } var thing = new Thing(); doIt(thing.logFoo.bind(thing)); //logs bar
同时也可以使用apply或call 来调用该方法或函数,让它在一个新的上下文中执行。
function Thing() { } Thing.prototype.foo = "bar"; Thing.prototype.logFoo = function () { function doIt() { console.log(this.foo); } doIt.apply(this); } function doItIndirectly(method) { method(); } var thing = new Thing(); doItIndirectly(thing.logFoo.bind(thing)); //logs bar
14 使用bind可以任意改变函数或方法的执行上下文,即使它没有被绑定到一个实例的原型上
function Thing() { } Thing.prototype.foo = "bar"; function logFoo(aStr) { console.log(aStr, this.foo); } var thing = new Thing(); logFoo.bind(thing)("using bind"); //logs "using bind bar" logFoo.apply(thing, ["using apply"]); //logs "using apply bar" logFoo.call(thing, "using call"); //logs "using call bar" logFoo("using nothing"); //logs "using nothing undefined"
15 对象中的this
可以在对象的任何方法中使用this来访问该对象的属性。这与用new得到的实例是不一样的
var obj = { foo: "bar", logFoo: function () { console.log(this.foo); } }; obj.logFoo(); //logs "bar"
通过this所拿到的只是该对象身上的属性而已
var obj = { foo: "bar", deeper: { logFoo: function () { console.log(this.foo); } } }; obj.deeper.logFoo(); //logs undefined
也可以不通过this,直接访问对象的属性
var obj = { foo: "bar", deeper: { logFoo: function () { console.log(obj.foo); } } }; obj.deeper.logFoo(); //logs "bar"
相关文章推荐
- JavaScript 学习笔记十四 this特性,静态方法 和实例方法,prototype
- JavaScript中的this学习笔记
- Javascript学习笔记之 函数篇(二) : this 的工作机制
- JavaScript学习笔记5-Javascript的this用法
- JavaScript 学习笔记 四 this指针
- JavaScript 中 关于 this 的学习笔记
- JavaScript学习笔记(3)---this
- 学习笔记——Javascript中的this
- Java程序员的JavaScript学习笔记(3——this/call/apply)
- Javascript学习笔记之 函数篇(二) : this 的工作机制
- JavaScript 学习笔记十四 this特性,静态方法 和实例方法,prototype
- [原]Java程序员的JavaScript学习笔记(3——this/call/apply)
- 大前端学习笔记整理【五】关于JavaScript中的关键字——this
- JavaScript 学习笔记十四 this特性,静态方法 和实例方法,prototype
- javascript语言精粹学习笔记之函数的四种this调用模式
- JavaScript之this学习笔记
- JavaScript 学习笔记 四 this指针
- 【学习笔记javascript设计模式与开发实践(this、call和apply)----2】
- 零基础入门-javaScript学习笔记之对象和不一样的this