普通函數 this 永遠指向它的調用對象app
var obj = { a:10, b:{ a:20, fn:function(){ console.log(this.a); } } } obj.b.fn(); //=> 20
對象 b 調用 fn 函數 this.a 爲 20。函數
var obj2 = { a:10, b:{ fn:function(){ console.log(this.a); } } } obj2.b.fn(); //=> undefined
對象 b 中無 a 字段, this.a 爲 undefined。this
var obj3 = { a:10, b:{ a:20, fn:function(){ console.log(this); console.log(this.a); } } } var j = obj3.b.fn; j(); //=> window, undefined
這裏直接獲取裏fn對象,沒有經過對象去調用。非嚴格模式下,this 默認指向全局對象window。spa
var obj4 = { a:10, b:{ a:20, fn:function(){ "use strict"; console.log(this); console.log(this.a); } } } var g = obj4.b.fn; g(); //=> undefined, TypeError: Cannot read property 'a' of undefined
而嚴格模式下, this 爲 undefined。prototype
function.bind(thisArg[, arg1[, arg2[, ...]]]) 最簡單的用法是建立一個函數,不論怎麼調用,這個函數都有一樣的 this 值。
function.call(thisArg, arg1, arg2, ...)、function.apply(thisArg, [argsArray]) call、apply 的做用相似都是爲調用函數指定this。rest
function fn() { return this.user; } console.log(fn.call({ user: "li" })); //=> li console.log(fn.apply({ user: "wang" })); //=> wang var bfn = fn.bind({ user: "gao" }); console.log(bfn()); //=> gao console.log(bfn.call({ user: "liu" })); //=> gao console.log(bfn.apply({ user: "liu" })); //=> gao console.log(bfn.bind({ user: "liu" })()); //=> gao var obj = { user: 'zhang', f: fn, g: bfn }; console.log(obj.f(), obj.g()); //=> zhang, gao
對 bind 產生的函數使用,再使用 call、apply、bind, 指向的 this 仍然是初次bind的值。code
function list() { return Array.prototype.slice.call(arguments); } console.log(list(1, 2, 3)); //=> [1, 2, 3] function list2(){ if(arguments){ arguments.__proto__.slice = Array.prototype.slice; return arguments.slice(); } } console.log(list2(4, 5, 6)); //=> [4, 5, 6] var leading37List = list.bind(null, 37); console.log(leading37List()); //=> [37] console.log(leading37List(1, 2, 3)); //=> [37, 1, 2, 3]
在函數代碼中,特殊對象 arguments 無需明確指出參數名,就能訪問它們。arguments 自帶 length 屬性, Array.prototype.slice.call(arguments) 能夠理解成 arguments.slice()對象
因爲箭頭函數不綁定this,它會捕獲其所在(即定義的位置)上下文的this值, 做爲本身的this值。繼承
var obj = { a: 10, b: function () { console.log(this.a, this) }, c: () => console.log(this.a, this), } obj.b(); //=> 10, Object{...} obj.c(); //=> undefined, window{...} obj.c.apply({ a: 'apply' }); //=> undefined, window{...} obj.c.call({ a: 'call' }); //=> undefined, window{...} obj.c.bind({ a: 'bind' })(); //=> undefined, window{...}
call() 、 apply() 、 bind() 方法對於箭頭函數來講只是傳入參數,對它的 this 毫無影響。作用域
function fn() { this.a = 20; this.b = () => console.log(this.a, this); } console.log((new fn()).b()) //=> 20, fn {a: 20, b: ƒ}
箭頭函數不會建立本身的this,它只會從本身的做用域鏈的上一層繼承this。
var lam = (...r) => { console.log(r); } lam(1,2,3); //=> Array : [1, 2, 3]
箭頭函數沒有arguments,取而代之用rest參數…解決。
var B = ()=>{ value:1; } var b = new B(); //=> TypeError: B is not a constructor
箭頭函數做爲匿名函數,沒有構造函數,不能使用new。
若是返回值是 引用類型 對象,那麼this指向的就是那個返回的對象;
若是返回值是 非引用類型 對象那麼this仍是指向函數的實例。
function fn() { this.user = '123'; return {}; } var a = new fn; console.log(a.user); //=> undefined
function fn() { this.user = '123'; return function(){}; } var a = new fn; console.log(a.user); //=> undefined
function fn() { this.user = '123'; return 123; } var a = new fn; console.log(a.user); //=> 123
function fn() { this.user = '123'; return undefined; } var a = new fn; console.log(a.user); //=> 123
function fn() { this.user = '123'; return null; } var a = new fn; console.log(a.user); //=> 123