// 示例一: var name = "windowsName"; function a() { var name = "Cherry"; console.log(this) // window console.log(this.name); // windowsName console.log("inner:" + this); // inner: Window } a(); // 至关于 window.a() console.log("outer:" + this) // outer:Window // 示例二: var name = "windowsName"; var a = { name: "Cherry", fn : function () { console.log(this) // a console.log(this.name); // Cherry } } window.a.fn(); // 至关于 a.fn() // 示例三: var name = "windowsName"; var a = { name: "Cherry", fn : function () { console.log(this) // window console.log(this.name); // windowsName } } var f = a.fn; f(); // 至关于 window.f() // 示例四: var name = "windowsName"; function fn() { var name = 'Cherry'; console.log(this) // window console.log(this.name); // windowsName innerFunction(); } function innerFunction () { console.log(this.name); // windowsName } fn() // 至关于 window.fn()
匿名函数的 this 永远指向 window
注意,这里咱们没有使用严格模式,若是使用严格模式的话,全局对象就是 undefined,会报错 Uncaught TypeError: Cannot read property 'name' of undefined。javascript
var name = "windowsName"; var a = { name : "Cherry", func1: function () { console.log(this.name) }, func2: function () { console.log(this) // a setTimeout(function () {// 匿名函数的 this 永远指向 window console.log(this) //window this.func1() },100); } }; a.func2() // this.func1 is not a function
1.箭头函数的 this 始终指向函数定义时的 this,而非执行时。
箭头函数中没有 this 绑定,必须经过查找做用域链来决定其值,若是箭头函数被非箭头函数包含,则 this 绑定的是最近一层非箭头函数的 this,不然,this 为 undefinedjava
var name = "windowsName"; var a = { name : "Cherry", func1: function () { console.log(this.name) }, func2: function () { setTimeout( () => { console.log(this) // a, 不是window this.func1() },100); } }; a.func2() // Cherry
2.在函数内部使用 _this = this。先将调用这个函数的对象保存在变量 _this 中,而后在函数中都使用这个 _this,这样 _this 就不会改变windows
var name = "windowsName"; var a = { name : "Cherry", func1: function () { console.log(this.name) }, func2: function () { var _this = this; setTimeout( function() { _this.func1() },100); } }; a.func2() // Cherry
3.使用 apply、call、bind 函数也是能够改变 this 的指向。
3.1 apply
语法:fun.apply(thisArg[, argsArray])
含义:该方法调用一个函数, 使用该函数(fun)的方法,同时改变函数中this的指向为thisArg。
参数:具备一个指定的this值,以及做为一个数组(或相似数组的对象)提供的参数
thisArg:在 fun 函数运行时指定的 this 值。注意:指定的 this 值并不必定是该函数执行时真正的 this 值,若是这个函数处于非严格模式下,则指定为 null 或 undefined 时会自动指向全局对象(浏览器中就是window对象),同时值为原始值(数字,字符串,布尔值)的 this 会指向该原始值的自动包装对象。
argsArray:一个数组或者类数组对象,其中的数组元素将做为单独的参数传给 fun 函数。若是该参数的值为null 或 undefined,则表示不须要传入任何参数。从ECMAScript 5 开始可使用类数组对象。数组
var a = { name : "Cherry", func1: function () { console.log(this.name) }, func2: function () { setTimeout( function () { this.func1() }.apply(a),100); // 此处省略第二个参数 } }; a.func2() // Cherry
3.2 call
语法:fun.call(thisArg[, arg1, arg2,....])
注:与apply用法相似,不一样之处:第二个参数为参数列表,使用逗号分割浏览器
var a = { name : "Cherry", func1: function () { console.log(this.name) }, func2: function () { setTimeout( function () { this.func1() }.call(a),100); // 此处省略第二个参数 } }; a.func2() // Cherry
3.3 bind
语法:fun.bind(thisArg[, arg1, arg2, ...])()
含义:bind()方法建立一个新的函数, 当被调用时,将其this关键字设置为提供的值,在调用新函数时,在任何提供以前提供一个给定的参数序列app
// 示例一: var a = { name : "Cherry", func1: function () { console.log(this.name) }, func2: function () { setTimeout( function () { this.func1() }.bind(a)(),100); } }; a.func2() // Cherry // 示例二: var a ={ name : "Cherry", fn : function (a,b) { console.log( a + b) } } var b = a.fn; b.bind(a,1,2)() // 3
对于不支持 bind 的浏览器,兼容性写法:函数
Function.prototype.bind = Function.prototype.bind || function(context) { var self = this; // console.log(this, context) return function() { console.log(arguments); // console [3,4] if ie<6-8> return self.apply(context, arguments); } } // 调用 var obj = { a: 1, b: 2, getCount: function(c, d) { return this.a + this.b + c + d; } }; window.a = window.b = 0; var func = obj.getCount.bind(obj)(3, 4); var apply = obj.getCount.apply(obj, [3, 4]); var call = obj.getCount.call(obj, 3, 4); console.log(func, apply, call) // 10 // 或者: Function.prototype.bind = Function.prototype.bind || function( context ){ var self = this; // 保存原函数 - 调用者 context = [].shift.call( arguments ), // 须要绑定的 this 上下文 args = [].slice.call( arguments ); 剩余的参数转化为数组 return function(){ // 返回一个新的函数 return self.apply( context, [].concat.call( args, [].slice.call( arguments ) ) ); // 执行新的函数的时候,会把以前传入context看成新函数体内的this // 而且组合两次分别传入的参数,做为新的函数的参数 } }; // 调用 var obj = { name: 'sven' }; var func = function( a, b, c, d ){ alert ( this.name ); // sven alert ( [ a, b, c, d ] ) // [ 1, 2, 3, 4 ] }.bind( obj, 1, 2 ); // obj ==> context func( 3, 4 );
4.构造函数Sum,若是咱们直接调用这个构造函数Sum(),那么这个this表明window对象;可是咱们对它进行实例化var obj = new Sum(),这样this.a上的this表明当前对象obj;this
function Sum(a, b){ console.log(this); // 1=>window; 2=>实例化对象obj this.a = a; this.b = b; this.add = function(){ console.log(this) // obj.add()=>实例化对象obj return this.a+this.b; } } // 1.直接调用: Sum(2, 3); console.log(a, b); // 2, 3 // 2.实例化: var obj = new Sum(2, 3); var num = obj.add(); console.log(num); // 5
new 的过程:prototype
function Person(name,age){ this.name = name this.age = age return [1,2,3] } var p = new Person('taurus_wood', 20) // [1, 2, 3] // 数组的类型是对象 function Person2(name,age){ this.name = name this.age = age return 1 } var p2 = new Person2('taurus_wood', 20) // {name:'taurus_wood', age: 20}
代码显示实例化过程code
var a = new myFunction("Li","Cherry"); // 伪代码表示: new myFunction{ var obj = {}; obj.__proto__ = myFunction.prototype; //创建了obj对象的原型链:obj->Animal.prototype->Object.prototype->null var result = myFunction.call(obj,"Li","Cherry"); return typeof result === 'obj'? result : obj; } // 或者: Function.method('new', function() { // this指向Function对象 // that是构造器对象 var that = Object.create(this.prototype); // other是调用构造器以后生成的对象,跟这行代码一个意思: var other = new Person() var other = this.apply(that, arguments); // 若是它返回的不一个对象,就返回该新对象 return (typeof other === 'object' && other) || that; })
1.单纯的函数调用
// 如上例: var name = "windowsName"; function a() { var name = "Cherry"; console.log(this.name); // windowsName console.log("inner:" + this); // inner: Window } a(); // 单纯的函数调用 console.log("outer:" + this) // outer: Window
2.函数做为对象的方法调用‘
// 如上例: var a = { name : "Cherry", func1: function () { console.log(this.name) }, func2: function () { setTimeout( function () { this.func1() }.bind(a)(),100); } }; a.func2() // Cherry 做为a对象的方法调用
3.使用构造函数调用函数 如上例 4.做为函数方法调用函数(call、apply) 在 JavaScript 中, 函数是对象。 JavaScript 函数有它的属性和方法。 call() 和 apply() 是预约义的函数方法。 两个方法可用于调用函数,两个方法的第一个参数必须是对象自己