JavaScript的this学习笔记

来源:互联网 发布:cad软件锁不起作用 编辑:程序博客网 时间:2024/05/18 01:33

1 浏览器宿主的全局环境中,this指的是window对象
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"
原创粉丝点击