this
全局作用域下的this
在全局作用域下
- 浏览器的this绑定为
window{globalObject} Node环境的this绑定为{},原因是Node环境下执行函数默认调用为function.call({})
函数作用域下的this
函数作用域下的this是动态绑定
函数的this是在调用时才绑定在其
FEC(函数执行上下文)中跟函数所处位置无关
仅跟函数被调用的方式有关
this的绑定规则
1.默认绑定
独立函数调用时,使用的默认绑定
function foo(){console.log(this);bar();}function bar(){console.log(this);}/* 独立函数调用 */foo(); // window window
2.隐式绑定
通过某个对象进行调用,使用的隐式绑定
const obj={name:'rv',say:function(){console.log(this.name);}}/* 通过对象调用 */obj.say();
3.apply(),call(),bind()
function foo(){console.log(this);}/* 独立函数调用 */foo() // window/* call */foo.call({id:1}) // {id:1}/* apply */foo.apply({id:2}) // {id:2}/* bind */const f=foo.bind({id:3})f() // {id:3}
4.new绑定
使用new关键字来调用函数,会执行如下操作
创建一个新对象
该对象执行prototype连接
对该对象进行this绑定(将该会像绑定到函数执行上下文的this上)
FEC{VOscopeChainthisBinging--------------代码执行}
- 如果函数没有返回其他对象,则表达式会返回该对象
this绑定优先级
new绑定>显式绑定>隐式绑定>默认绑定
function foo(){console.log(this);}var obj={foo:foo;}/* new绑定高于显式绑定 */var bar=foo.bind("abc");new bar() // foo:{}/* 显式绑定高于于隐式绑定 */obj.foo.call("abc") // String{"abc"}/* bind高于call和apply */foo.bind("abc").call("cba") // String{"abc"}
特殊情况——忽略显式绑定
当显式绑定传入null,undefined时,自动将this绑定成全局对象
function foo(){console.log(this)}foo.apply(null) // windowfoo.call(undefined) // window
特殊情况——间接函数引用
var obj1={foo:function(){console.log(this)}}var obj2={};/*此处不加';'代码解析会出现问题,发出报错Uncaught TypeError: Cannot set properties of undefined (setting 'bar')*/(obj2.bar=obj1.foo)() // window
ES6 箭头函数
省略语法糖
参数只有一个时,
()可以省略函数执行体只有一行且将执行结果作为函数返回值时,
{}可以省略函数执行体只有一行且返回一个对象,
{}省略的同时须加()告诉js解析器此处为整体var bar=()=>({name:'rv',age:18})
箭头函数的this获取
this永远指向定义时的上层作用域,任意绑定均不改变其this指向
测试面试题
第一题
var name='window';var person={name:'person',sayName:function(){console.log(this.name);}}function sayName(){var s=person.sayName;s();person.sayName();(person.sayName)();(b=person.sayName)();}// 答案/*window(独立函数调用)person(隐式绑定)person(隐式绑定)window(独立函数调用)*/
第二题
var name='window';var person1={name:'person1',foo1:function(){console.log(this.name);},foo2:()=>console.log(this.name),foo3:function(){return function(){console.log(this..name);}},foo4:function(){return ()=>console.log(this.name)}}var person2={name:'person2'};person1.foo1();person1.foo1.call(person2);person1.foo2();person1.foo2.call(person2);person1.foo3()();person1.foo3.call(person2)();person.foo3().call(person2);person1.foo4();person1.foo4.call(person2)();person1.foo4().call(person2);// 答案/*person1(隐式绑定)person2(显式绑定)window(箭头函数,上层作用域为window)window(箭头函数,上层作用域为window)window(独立函数调用)window(独立函数调用)person2(显式绑定)person1(箭头函数,上层作用域为person1)person2(箭头函数,上层作用域为person2)person1(箭头函数,上层作用域为person1)*/
第三题
var name='window';function Person(name){this.name=name;this.foo1=function(){console.log(this.name);};this.foo2=()=>console.log(this.name);this.foo3=function(){return function(){console.log(this.name);};};this.foo4=function(){return ()=>{console.log(this.name);};};}var person1=new Person('person1');var person2=new Person('person2');person1.foo1();person1.foo1.call(person2);person1.foo2();person1.foo2.call(person2);person1.foo3()();person1.foo3.call(person2)();person1.foo3().call(person2);person1.foo4()();person1.foo4.call(person2)();person1.foo4().call(person2);// 答案/*person1(隐式绑定)person2(显式>隐式)person1(箭头函数,上层作用域person1)person1(箭头函数,上层作用域person1)window(默认绑定)window(默认绑定)person2(显式绑定)person1(箭头函数,上层作用域person1)person2(箭头函数,上层作用域person2)person1(箭头函数,上层作用域person1)*/
第四题
var name='window';function Person(name){this.name=name;this.obj={name:'obj',foo1(){return function(){console.log(this.name);};},foo2(){return ()=>console.log(this.name);},}}var person1=new Person('person1');var person2=new Person('person2');person1.obj.foo1()();person1.obj.foo1.call(person2)();person1.obj.foo1().call(person2);person1.obj.foo2()();person1.obj.foo2.call(person2)();person1.obj.foo2().call(person2);// 答案/*windowwindowperson2objperson2o*/
