this指向


 全局环境
    
        window    
        <script type="text/javascript">
            console.log(this);    // 全局环境 window
        </script>
    
    事件处理函数
    
        DOM事件处理函数
        <div id="box">div</div>
        <script type="text/javascript">
            var box = document.getElementById('box');
            box.onclick = function () {
                console.log(this);    // 事件处理函数中的this,该事件由谁触发,this指向的就是谁
            }
        </script>
    
        内联事件处理函数
        <div id="box1" onclick="console.log(this)">div1</div><!-- this: <div id="box1" onclick="console.log(this)">div1</div> 指向触发事件的元素-->
        <div id="box2" onclick="( (function (){console.log(this)})() )">div2</div><!-- this: window -->    
    
    函数内部
    
        函数直接执行
            非严格模式下:
                1、默认指向全局对象
                (1)浏览器
                (2)node
                    a: node交互界面中;
                    b: js文件中;
                    node_this.js 文件中直接console.log(this);用node方式打开输出{}console.log(this === module.exports);输出true
                    node交互界面中直接输入this 输出的才是gobal
            
            严格模式下(前面省略window,浏览器严格模式支持)
                undefined
    
        call,apply,bind 把this的值从一个执行环境传入另一个执行环境,call和apply的参数差异,如果传入的不是对象会调用相对的构造函数,进行隐式转换
            <script type="text/javascript">
                function fn() {
                    console.log(this); 
                }
                var fn1 = fn.bind(1);
                fn1(); // Number {1}__proto__: Number[[PrimitiveValue]]: 1
            </script>
    
            call
                <script type="text/javascript">
                    function fn(m,n) {
                        console.log(this.a,m,n); // 1 2 3
                    }
                    fn.call({a:1},2,3);
                    /* 函数.call 会直接调用该函数
                    call的第0个参数就是函数执行时候的this
                    后面的参数是函数执行的时候的参数
                    */
                </script>
    
            bind 返回一个新函数,内部this指向被修改,只会改变一次
                <script type="text/javascript">
                    function fn() {
                        console.log(this.a); 
                    }
                    fn.bind(); // 没有输出 函数.bind 改变this指向,并不调用函数
                    var fn1 = fn.bind({a:1});
                    console.log(fn1); // fn() {console.log(this.a);}
                    fn(); // undefined 并不会改变原有fn的指向
                    fn1(); // 1
                    var fn2 = fn.bind({a:2});
                    var fn3 = fn.bind({a:3});
                    fn2(); // 2
                    fn3(); // 3
                    var fn4 = fn1.bind({a:4}); // fn1该指向只能改一次
                    fn4(); // 1
                </script>
    
    箭头函数内部
    
        与定义时的环境中this一致
            点击元素定时改变
            <div id="box">box</div>
            <script type="text/javascript">
                var box = document.querySelector('#box');
                box.onclick = function () {
                    setTimeout(()=>{
                        this.style.backgroundColor = 'red';
                    },500);
                    // 箭头函数被定义的时候指向的是box,所以里面的this就指向box
                }
            </script>
    
        bind,call不能修改其内部指向
        <script type="text/javascript">
            var fn = ()=>{
                console.log(this);
            };
            var fn1 = fn.bind({});
            fn1();    // window
        </script>
    
        全局中定义箭头函数
            全局对象
        
        对象内函数定义箭头函数
            <script type="text/javascript">
                var a = 1;
                var obj = {
                    a: 2,
                    fn1: ()=>{
                        console.log(this.a);    //this指向window
                    },
                    fn2: function () {
                        console.log(this.a);    //this指向obj
                    }
                };
                obj.fn1(); // 1 定义时的环境和obj所在环境一样 this指向window
                obj.fn2(); // 2 obj调用 this指向obj
            </script>
        对象内函数返回箭头函数
            <script type="text/javascript">
                var a = 1;
                var obj = {
                    a: 2,
                    fn1: function () {
                        console.log(this.a); // 2
                        return function () {
                            console.log(this.a); // 1
                        }
                    },
                    fn2: ()=>{
                        console.log(this.a); // 1
                        return ()=>{
                            console.log(this.a); // 1    
                        }
                    }
                };
                // obj.fn1()(); // 1 等同于下面两行代码  obj.fn1()返回的是一个函数 obj.fn1()()是window调用
                var innerFn1 = obj.fn1(); 
                innerFn1(); // 1
                // obj.fn2()(); // 1 
                var innerFn2 = obj.fn2(); 
                innerFn2(); // 1
            </script>
    
    对象方法内部
        
        当函数作为对象里的方法被调用时:调用该函数的对象
            <script type="text/javascript">
                var a = 1;
                var obj = {
                    a: 2,
                    fn: function () {
                        console.log(this.a);
                    }
                }
                obj.fn();     //    2 this指向调用该函数的对象
                obj.fn.bind({a: 'haha'})();    // haha
            </script>
        
        对象后续附属上的方法调用:调用该函数的对象
            <script type="text/javascript">
                var obj = {
                    a: 1
                }
                var fn = function () {
                    console.log(this.a);
                }
                obj.fn = fn;
                obj.fn();     //    1 this指向调用该函数的对象
                var fn1 = ()=>{
                    console.log(this.a);
                }
                obj.fn1 = fn1;
                obj.fn1();     //    undefined this指向window
            </script>
        作为函数内嵌套多层的方法调用:就近绑定
            <script type="text/javascript">
                var a = 1;
                var obj = {
                    a: 2,
                    b: {
                        a: 3,
                        fn: function () {
                            console.log(this.a);
                        },
                        fn1: ()=>{
                            console.log(this.a);
                        }
                    }
                }
                obj.b.fn();     //    3 this指向调用该函数的对象b
                var temp = obj.b.fn;    // temp赋值为函数,并没有调用执行
                temp();        // 1 this指向调用该函数的对象window
                obj.b.fn1();    // 1 this指向定义该函数时的环境window
            </script>

    构造函数中

        构造函数中没有显示return
            <script type="text/javascript">
                function Fn() {
                    this.a = 1;
                }
                var f = new Fn();
                console.log(f);    // Fn {a: 1} this指向new关键字创建实例化之后的实例f
            </script>
        构造函数中显示return
            return 对象
                <script type="text/javascript">
                    function Fn() {
                        this.a = 1;
                        return {};
                    }
                    var f = new Fn();
                    console.log(f);    // {} return非null的对象,实例化的结果就是返回出的对象
                </script>
            return 非对象
                <script type="text/javascript">
                    function Fn() {
                        this.a = 1;
                        return 2;
                    }
                    var f = new Fn();
                    console.log(f);    // Fn {a: 1} return非对象,实例化的结果就是new的实例
                </script>

    原型链上函数

        调用该函数的对象
            <script type="text/javascript">
                var p = {
                    a: 1,
                    fn: function () {
                        console.log(this.a);
                    }
                }
                var c = Object.create(p);    //     以p为模板创建c
                console.log(c);        // {}__proto__: Object
                console.log(c.a);    // 1 一个对象上面没有函数,会找proto
                console.log(c.__proto__);    // {a: 1}
                c.fn();        // 1
            </script>

    getter 和 setter中

        get访问
        set设置
            <script type="text/javascript">
                var obj = {
                    n: 1,
                    m: 2,
                    get sum() {
                        console.log('正在访问sum...');
                        return this.n + this.m;
                    },
                    set sum(v) {    // 必须有一个参数 否则报错
                        console.log('正在设置sum...');
                        this.n = v/2;
                        this.m = v/2;
                    }
                }
                console.log(obj.sum);        // 3
                obj.sum = 40;
                console.log(obj.n);     // 20
            </script>

posted @ 2018-12-28 10:37  江离白芷  阅读(151)  评论(0编辑  收藏  举报