JavaScript——this关键字

 引入

首先运行如下js代码

var obj={
            color:"red",         //这个color是对象的属性,不是函数形参
            changecolor:function(color){
                obj.color=color  //给对象属性更新值
            }
        }
        obj.changecolor("blue")
        console.log(obj.color)

        //结果为blue

        可以看出当给一个对象设置成员值时:如果已经有这个成员了就会覆盖之前值

var obj={         
            createcolor:function(color){
                obj.color=color  //给对象创建新属性
            }
        }
        obj.createcolor("blue")
        console.log(obj.color)

//结果为blue

        我们又可以看出给一个对象设置属性值时:如果没有这个属性就会创建一个新的属性并赋值

        而且对象花括号里冒号后面保存的不是函数就是基本属性,保存的函数就称之为方法

var obj={
            width:"200px",
            height:"200px",
            color:"red",
            onclick:function(color){
                var obj={name:"jack",age:20}
                obj.color=color //blue就近,给上面的obj创建color属性并赋值blue
            }
        }
        obj.onclick("blue")
        console.log(obj.color) //这里的obj是外面的obj
        //运行结果为red

         从上面的代码我们可以看到obj.color=color是对onclick函数里面的obj运行的,所以创建了一个color属性并赋值blue,而console.log(obj.color)则是对onclick函数外面的obj来说的,所以打印结果是red

this的定义与作用

this代表的是执行这个this代码的环境对象,this在脚本中代表的是window全局对象

这并不便于我们理解,我们简单的看如下代码

console.log(this)
        //运行结果为window 

function fn() {
            console.log(this)
        }
        fn()

        //运行结果为window

        var obj = {
            name: "Karen",
            sayname: function () {
                console.log(this)
            }
        }
        obj.sayname()

        //运行结果为{name:“Karen”,...}

        可以很清楚的看到上面打印的是window,下面打印的是obj这个对象

我们可以用一个规律,两个步骤解释一下这句话

        1.找到距离this最近的一个function(嵌套级)

        2.看是谁调用这个function函数,this就是这个函数的调用者

        在js程序中无论多复杂的程序this只需要看离最近(嵌套而不是平级关系)的function的这个单词的调用者

        如上面的fn()==>window.fn()  this最近的function是fn,fn的调用者是window,所以this就是window

        同理,函数sayname的调用者是obj,所以this是obj

举例

再举几个例子

var obj={
            name:"芭比",
            son:{
                name:"儿子",
                say:function(){
                    console.log(this)
                }
            }
        }
        obj.son.say()

        打印的是son这个对象{name: '儿子', say: ƒ},调用者是obj.son

var obj={
            name:"芭比",
            son:{
                name:"儿子",
                say:function(){
                    console.log(this)
                }
            }
        }
        var a=obj.son.say
        a()

         obj.son.say赋给a,a()调用者为window,this是window

function fn(){
            return function fm(){
                console.log(this)
            }
        }
        var obj={}
        obj.fm=fn()
        console.log(obj)
        obj.fm()
        fn()() //window

         定义对象obj

        为obj增加成员属性fm,并将fn运行结果fm函数赋给它

        打印obj  {fm:f}

        运行obj的fm方法,this的调用者为obj,打印obj  {fm:f}

        fn()()  this的调用者为window,运行结果为window

可以总结出以下常见函数调用形式的规律

          运行函数                  this调用者 

             fn()                        //  window

            obj.fn()                   //  obj

            obj.xx.xx2()            //  obj.xx

            (function(){})()        //  window

            fn()()                      //  window

            fn()[1]()                  //  fn()返回的数组

例题

下面我们来看几道题

1.

var name = "ilil"; //window本来就有name属性,值为空白
        var obj = {
            name: "huahua",
            prop: {
                name: "xixi",
                getname: function () {
                    return this.name
                }
            }
        };
        console.log(obj.prop.getname()); //调用者为obj.prop
        var test = obj.prop.getname;  //将函数赋给test
        console.log(test());     //test()调用者为window

        首先打印的是obj.prop.getname(),调用者为obj.prop,this.name就是obj.prop.name,就是xixi

        接着将obj.prop.getname函数赋值给test,test是全局对象,所以test()的调用者是window,this.name打印的是window的name属性,就是lili

2.

var object={
         who:"world",
         greet(){
             return this.who;
         }
        };
        console.log(object.greet())

        object.greet()    得到返回值 this.who,this指向的是object,object.who的值为world

3.

function Foo() {
            getName = function () {  //运行到这没有getname变量,就去全局作用域里找
                console.log(1);
            };
            return this;
        }
        var getName = function () {
            console.log(4);
        };
        Foo().getName(); //foo结果是window,window的属性getname

        1.Foo()调用时,需要使用getName变量,但是Foo内部没有这个变量,就去外面的全局作用域找

        2.找到了之后就继续运行,将function(){console.log(1)},这个匿名函数赋值给getName,函数Foo的返回值是this,这里的this是window

        3.Foo().getName() ==》window.getName()   上一步骤,getName的值已经改变了,所以console.log打印的是1,而不是4

4.

加深一下对 对象所指向的内存空间的理解

var a={n:1};
    var b=a;
    a.x=a={n:2};
    console.log(a.x); //undefined
    console.log(b.x); //{x:2}

var a=b=c;

a是最后赋值(引用)的,但是a的引用声明是一开始就有了

我们知道上述规律就可以分析

1.   a.x先取空间,但是不赋值,这里取的空间是{n:1,x:}里的a.x

2.   a={n:2}   由{n:1,x:}指向另一个内存空间{n:2}

3.   此时a.x={n:2}这个赋值赋给原来的内存空间{n:1,x:}中,即为{n:1,x:{x:2}}

4.   此时a不指向{n:1,x:{n:2}}这个内存空间指向{n:2},由b=a的b指向{n:1,x:{x:2}}

   

 补充

关于全局对象window

function fn(){}

var a=20

console.log(fn)  //console.log(window.fn)

console.log(a)  //console.log(window.a)

        var a=20 全局变量会在脚本执行时,把变量名设置为全局对象window的属性

        function fn(){console.log(this)}全局函数会在脚本执行时,把函数设置为全局对象window的方法

        所以在调用时a,其实是window.a,函数fn同理

var a=this;
        console.log(a);
        function fn(){
            console.log(this)
        }
        fn() //window.fn()  对象调用方法
        /*运行结果
            window
            window
        */

关于函数的两种写法

        // 函数的写法其实有两种

        // 1.声明函数:直接在作用域写一个函数
        function fn(){

        }
        // 2.定义一个函数:直接创建一个函数,把它当作数据一样
            var a=function(){}
            var obj={
                say:function(){}
            }
            var arr=[20,function(){},300]

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值