在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
深入理解Js中的this
作用域我们先来了解一下 var a = 1; var s = function(){ console.log(a); }; (function(){ var a = 2; s(); // 1 })(); 调用s()是打印的a为1,此为静态作用域,也就是声明时即规定作用域,而假如是动态作用域的话在此处会打印2。现在大部分语言都采用静态作用域,比如 全局作用域直接声明在顶层的变量或方法就运行在全局作用域,借用函数的 function s(){} console.dir(s); /* ... [[Scopes]]: Scopes[1] 0: Global ... */ // 可以看见声明的s函数运行的上下文环境是全局作用域 函数作用域当声明一个函数后,在函数内部声明的方法或者成员的运行环境就是此函数的函数作用域 (function localContext(){ var a = 1; function s(){ return a; } console.dir(s); })(); /* ... [[Scopes]]: Scopes[2] 0: Closure (localContext) {a: 1} 1: Global ... */ // 可以看见声明的s函数运行的上下文环境是函数localContext的作用域,也可以称为局部作用域 块级作用域代码块内如果存在 { let a = 1; function s(){return a;} console.dir(s); /* ... [[Scopes]]: Scopes[2] 0: Block {a: 1} 1: Global ... */ } // 可以看见声明的s函数运行的上下文环境是Block块级作用域,也是局部作用域 分析我们在使用 var obj = { name: 1, say: function() { return this.name; } }; window.name = 2; window.say = obj.say; console.log(obj.say()); // 1 console.log(window.say()); // 2 产生这样的结果的原因就是因为使用了 使用我们需要记住, 默认绑定最常用的函数调用类型即独立函数调用,这个也是优先级最低的一个,此时 var a = 1; // 变量声明到全局对象中 function f1() { return this.a; } function f2() { "use strict"; return this; } console.log(f1()); // 1 // 实际上是调用window.f1()而this永远指向调用者即window console.log(f2()); // undefined // 实际上是调用 window.f2() 此时由于严格模式use strict所以在函数内部this为undefined 隐式绑定对象属性引用链中只有最顶层或者说最后一层会影响 function f() { console.log(this.a); } var obj1 = { a: 1, f: f }; var obj2 = { a: 11, obj1: obj1 }; obj2.obj1.f(); // 1 // 最后一层调用者即obj1 function f() { console.log(this.a); } var obj1 = { a: 1, f: f }; var obj2 = { a: 11, }; obj2.f = obj1.f; // 间接引用 obj2.f(); // 11 // 调用者即为obj2 显示绑定如果我们想把某个函数强制在某个环境即对象上,那么就可以使用 window.name = "A"; // 挂载到window对象的name document.name = "B"; // 挂载到document对象的name var s = { // 自定义一个对象s name: "C" } var rollCall = { name: "Teacher", sayName: function(){ console.log(this.name); } } rollCall.sayName(); // Teacher // apply rollCall.sayName.apply(); // A // 不传参默认绑定window rollCall.sayName.apply(window); // A // 绑定window对象 rollCall.sayName.apply(document); // B // 绑定document对象 rollCall.sayName.apply(s); // C // 绑定自定义对象 // call rollCall.sayName.call(); // A // 不传参默认绑定window rollCall.sayName.call(window); // A // 绑定window对象 rollCall.sayName.call(document); // B // 绑定document对象 rollCall.sayName.call(s); // C // 绑定自定义对象 // bind // 最后一个()是为让其执行 rollCall.sayName.bind()(); //A // 不传参默认绑定window rollCall.sayName.bind(window)(); //A // 绑定window对象 rollCall.sayName.bind(document)(); //B // 绑定document对象 rollCall.sayName.bind(s)(); // C // 绑定自定义对象 new绑定在 创建一个空的简单 function _new(base,...args){ var obj = {}; obj.__proto__ = base.prototype; base.apply(obj, args); return obj; } function Funct(a) { this.a = a; } var f1 = new Funct(1); console.log(f1.a); // 1 var f2 = _new(Funct, 1); console.log(f2.a); // 1 箭头函数箭头函数没有单独的 window.name = 1; var obj = { name: 11, say: function(){ const f1 = () => { return this.name; } console.log(f1()); // 11 // 直接调用者为window 但是由于箭头函数不绑定this所以取得context中的this即obj对象 const f2 = function(){ return this.name; } console.log(f2()); // 1 // 直接调用者为window 普通函数所以 return this.name; } } console.log(obj.say()); // 11 // 直接调用者为obj 执行过程中的函数内context的this为obj对象 示例function s(){ console.log(this); } // window中直接调用 // 非 use strict s(); // Window // 等同于window.s(),调用者为window // window是Window的一个实例 // window instanceof Window //true // 新建对象s1 var s1 = { t1: function(){ // 测试this指向调用者 console.log(this); // s1 s(); // Window // 此次调用仍然相当 window.s(),调用者为window }, t2: () => { // 测试箭头函数,this并未指向调用者 console.log(this); }, t3: { // 测试对象中的对象 tt1: function() { console.log(this); } }, t4: { // 测试箭头函数以及非函数调用this并未指向调用者 tt1: () => { console.log(this); } }, t5: function(){ // 测试函数调用时箭头函数的this的指向,其指向了上一层对象的调用者 return { tt1: () => { console.log(this); } } } } s1.t1(); // s1对象 // 此处的调用者为 s1 所以打印对象为 s1 s1.t2(); // Window s1.t3.tt1(); // s1.t3对象 s1.t4.tt1(); // Window s1.t5().tt1(); // s1对象 到此这篇关于深入理解Js中的this的文章就介绍到这了,更多相关深入理解Js中的this内容请搜索极客世界以前的文章或继续浏览下面的相关文章希望大家以后多多支持极客世界! |
请发表评论