# this 指向
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 function foo ( ) { console .log ( this .a ); } function doFoo ( ) { foo (); } var obj = { a : 1 , doFoo : doFoo }; var a = 2 ; obj.doFoo ()
obj 调用 doFoo 方法,doFoo 中执行 foo 函数,函数调用函数则当作由 window(global)调用,所以 this 指向全局的 a=2
1 2 3 4 5 6 7 8 9 10 11 12 var a = 10 var obj = { a : 20 , say : () => { console .log (this .a ) } } obj.say () var anotherObj = { a : 30 } obj.say .apply (anotherObj)
obj 调用 say,但由于属性值为箭头函数(箭头函数没有 this),所以不能作为 obj 上的方法调用,this 指向上一层,上一层为 window,是所以输出 10 apply 可以改变函数的 this,但箭头函数无 this,所以无法改变,仍是由全局调用
1 2 3 4 5 function a ( ) { console .log (this ); } a.call (null );
根据 ECMAScript262 规范规定:如果第一个参数传入的对象调用者是 null 或者 undefined,call 方法将把全局对象(浏览器上是 window 对象)作为 this 的值。所以,不管传入 null 还是 undefined,其 this 都是全局对象 window 或 global。 要注意的是,在严格模式中,null 就是 null,undefined 就是 undefined
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 var obj = { say : function ( ) { var f1 = ( ) => { console .log ("1111" , this ); } f1 (); }, pro : { getPro :() => { console .log (this ); } } } var o = obj.say ;o ();obj.say (); obj.pro .getPro ();
o 在全局调用,所以 this 是 window 或 global obj 调用 say 方法,而 say 方法中执行 fn 箭头函数,可以认为是函数调函数,但由于箭头函数无 this,指向上一层级,所以是 obj 调用,该处 this 指向 obj 不同于上,这里是 pro 调用了 getPro 这个箭头函数,这里的 this 指向上一层级 window(这里 node 中打印了空对象)(注意这里的上一层级并不是 obj)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 var obj = { foo : "bar" , func : function ( ) { var self = this ; console .log (this .foo ); console .log (self.foo ); (function ( ) { console .log (this .foo ); console .log (self.foo ); }()); } }; obj.func ();
在立即执行函数中,this 指向全局(特别注意,并非有括号就是立即执行函数,(obj.func)() 本质上还是 obj.func (),this 指向还是 obj) self 通过作用域链找到 func 中的 self,该 self 保存着 this 指向 obj
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 var length = 10 ;function fn ( ) { console .log (this .length ); } var obj = { length : 5 , method : function (fn ) { fn (); arguments [0 ](); } }; obj.method (fn, 1 );
函数调函数,由全局调用arguments[0]()
可以看作 arguments.fn()
fn 指向 arguments
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 var x = 3 ;var y = 4 ;var obj = { x : 1 , y : 6 , getX : function ( ) { var x = 5 ; return function ( ) { return this .x ; }(); }, getY : function ( ) { var y = 7 ; return this .y ; } } console .log (obj.getX ()) console .log (obj.getY ())
匿名函数的 this 是指向全局对象的,所以 this 指向 window,会打印出 3; getY 是由 obj 调用的,所以其 this 指向的是 obj 对象,会打印出 6。
1 2 3 4 5 6 7 8 9 function a (xx ){ this .x = xx; return this }; var x = a (5 );var y = a (6 );console .log (x.x ) console .log (y.x )
return this 后,x 和 y 都是 global,global.x 就是 6 如果是在浏览器中,则代码运行顺序如下 window.x = 5 -> window.x = window -> window.x = 6 -> window.y = window 所以结果输出则为 6.x(undefined),window.x(6)
# 原型
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 function Person (name ) { this .name = name } var p2 = new Person ('king' );console .log (p2.__proto__ ) console .log (p2.__proto__ .__proto__ ) console .log (p2.__proto__ .__proto__ .__proto__ ) console .log (p2.__proto__ .__proto__ .__proto__ .__proto__ )console .log (p2.__proto__ .__proto__ .__proto__ .__proto__ .__proto__ )console .log (p2.constructor )console .log (p2.prototype )console .log (Person .constructor )console .log (Person .prototype )console .log (Person .prototype .constructor )console .log (Person .prototype .__proto__ )console .log (Person .__proto__ ) console .log (Function .prototype .__proto__ )console .log (Function .__proto__ )console .log (Object .__proto__ )console .log (Object .prototype .__proto__ )
1 2 3 4 5 6 7 8 9 function changeObjProperty (o ) { o.name = "baidu" o = new Object () o.name = "byte" } let company = new Object ();changeObjProperty (company);console .log (company.name );
输出为 baidu,传入参数为 company,则此时变量 o 引用的是 company,可以直接对对象进行操作,如果此时重新赋值 new Object,那么此时 o 指向新建的对象,此时 o 再进行的操作都与 company 无关
1 2 3 4 5 function Person ( ) {}function Father ( ) {}Father .prototype = new Person ()const son = new Father ()
指向 Person,虽然在原型链上,但原型继承无法继承构造函数