JavaScript-基础篇-This指向问题-上

1. This 的指向问题

默认绑定规则

    console.log(this) // window, strict模式下返回undefined    function test() {        console.log(this); // window    }    test(); // 纯粹的调用 (Simple call) ==> window.test() 指向window

隐式绑定规则 (谁呼叫就指向谁)

    let a = 0;    let obj = {        a:2,        foo: function(){            console.log(this); // obj  =>  obj 呼叫了 foo, 因此 foo 里的 this 指向为 obj        }    }    obj.foo()
    let a = 0;    let obj = {        a:2,        foo: function(){            console.log(this); // 返回obj            function test(){                console.log(this) // window            }            test() // obj 呼叫了 foo, 但 test 并不是由 obj呼叫的, 而是纯粹调用, 因此 this 指向 window        }    }    obj.foo()

IIFE

    let a = 0;    let obj = {        a:2,        foo: function(){            (function(){                console.log(this); // window            })(); // 立即函式(IIFE)都属于纯粹调用, 所以 this 的指向都是 window        }    }    obj.foo()

闭包

    let a = 0;    let obj = {        a: 2,        foo: function () {            function test() {                console.log(this) // window            }            return test        }    }        obj.foo()() // obj.foo() 的返回值为 test, 因此该表达式 == test() 属于纯粹调用, 因此 this 指向 window

变数赋值的情况

    let a = 0;    function foo(){        console.log(this);    }        let obj = {        a:2,        foo // ES6简写    }    obj.foo() // obj    let bar = obj.foo // obj.foo == foo, 该表达式的结果是把 foo 的引用地址赋值给了 bar    bar() // 因此 bar == foo , 属于纯粹调用, this 的指向为 window

参数赋值的情况

    let a = 0;    function foo(){        console.log(this);    }    function bar(fn){        // 将传进来的 obj.foo == foo 赋值给形参 fn        fn() // == foo()  属于纯粹调用, 因此 this 的指向为 window        // 因此 this 的指向只需要关注函式最终是如何执行的即可    }    let obj = {        a:2,        foo    }    bar(obj.foo) // obj.foo == foo 作为实参

阿里巴巴面试题

    var name = 222;    var a = {        name: 111,        say: function () {            console.log(this.name);        },    };    var fun = a.say;    fun(); // ?    a.say(); // ?    var b = {        name: 333,        say: function (fun) {            fun();         },    };    b.say(a.say); // ?    b.say = a.say;    b.say(); // ?
答案: 
    var name = 222;    var a = {        name: 111,        say: function () {            console.log(this.name);        },    };    var fun = a.say;    fun(); // 222    a.say(); // 111    var b = {        name: 333,        say: function (fun) {            fun(); // 在这里执行了 (a.say)(), 因此是纯粹调用, this 的指向为 window        },    };    b.say(a.say); // 222    b.say = a.say;    b.say(); // 333

forEach 内的 this 指向

    let arr = [1,2,3,4,5]    let obj = { name : "obj" }    // 在对应的api接口文档中指明    arr.forEach(function(item, index, arr){        console.log(this); // 每次都输出 obj    }, obj) // 这里的 obj 就是 arr.forEach 遍历时的 this 指向
arr.forEach(function callback(currentValue[, index[, array]]) {    //your iterator}[, thisArg]);参数: callback这个 callback 函式将会把 Array 中的每一个元素作为参数,带进本 callback 函式里,每个元素各执行一次,接收三个参数:currentValue代表目前被处理中的 Array 之中的那个元素。index (选择性)代表目前被处理中的 Array 之中的那个元素的 index.array (选择性)呼叫 forEach() 方法的那个 Array 本身,也就是上面语法中的 arr。thisArg (选择性)执行 callback 回呼函式的 this(即参考之 Object)值。source: https://developer.mozilla.org/zh-TW/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach

显式绑定: call, apply, bind

    function foo() {        console.log(this); // 打印    }    let obj = {        a: 2,        foo    }    let bar = obj.foo    obj.foo() // obj        以下三种方式都能改变 this 的指向, 将 bar函式 的 this 指向改为 obj    bar.call(obj) // obj    bar.apply(obj) // obj    bar.bind(obj)() // obj

补充

function foo(){    console.log(this)}foo.call(1) // Number {1}foo.call(null) // this 指向 windowfoo.apply(undefined) // this 指向 window

建构式的显式绑定实例

    function Product(name, price) {        this.name = name;        this.price = price;        if (price < 0)            throw RangeError('Cannot create product "' + name + '" with a negative price');        return this;    }    function Food(name, price) {        // new后this的指向就是这个实例物件        console.log(this);        Product.call(this, name, price);        this.category = 'food';    }    Food.prototype = new Product();    function Toy(name, price) {        Product.call(this, name, price);        this.category = 'toy';    }    Toy.prototype = new Product();    let cheese = new Food('feta', 5);    console.log(cheese); // Food {name: 'feta', price: 5, category: 'food'}    let fun = new Toy('robot', 40);    console.log(fun); // Toy {name: 'robot', price: 40, category: 'toy'}

new 绑定

function Person(name='haewon', age=6){    this.name = name    this.age = age    console.log(this) // 这里会打印 this}let me = new Person('pupu', 12) // 打印 Person {name: 'pupu', age: 12}, this 的指向为实例化的物件Person() // 打印 window; 同时 window.name 的值为 'haewon'; window.age 的值为 6

总结

1. 默认绑定: console.log(this=== window)  ==> true 2. 隐式绑定: (谁呼叫就指向谁) :3. 显式绑定: call, apply, bind4. new 绑定规则;

优先级

1. 显式绑定 > 隐式绑定
    function foo(){            console.log(this.a);        }        let obj1 ={            a:'obj1',            foo        }        let obj2 ={            a:'obj2',            foo        }        obj1.foo() // obj1        obj2.foo() // obj2        obj1.foo.call(obj2) // obj2        obj2.foo.call(obj1) // obj1
2. new 绑定 > 显式绑定
function foo(b){        this.a = b    }    let obj1 = {}    let bar = foo.bind(obj1)    bar(2)    console.log(obj1.a) // 2    let bar_child = new bar(99) // new 将 this 的指向更改为 bar_child    console.log(obj1.a); // 2    console.log(bar_child.a); // {a:99}

以上是我整理好的资料,希望有帮助到大家

关于作者: 网站小编

码农网专注IT技术教程资源分享平台,学习资源下载网站,58码农网包含计算机技术、网站程序源码下载、编程技术论坛、互联网资源下载等产品服务,提供原创、优质、完整内容的专业码农交流分享平台。

热门文章