const g = (f) => f(); // No base ref.const h = refObj.func;const j = () => refObj.func;
g(refObj.func);h(); // No base ref.j()(); // No base ref.(0, refObj.func)(); // Another common pattern to remove the base ref.
function f1(){console.log(this);}
function f2(){console.log(this);}
function f3(){console.log(this);}
const o = {f1,f2,[Symbol.unscopables]: {f2: true}};
f1(); // Logs `globalThis`.
with(o){f1(); // Logs `o`.f2(); // `f2` is unscopable, so this logs `globalThis`.f3(); // `f3` is not on `o`, so this logs `globalThis`.}
和:
"use strict";
function f(){console.log(this);}
f(); // Logs `undefined`.
// `with` statements are not allowed in strict-mode code.
function f(){console.log(this);}
const myObj = {},g = f.bind(myObj),h = (m) => m();
// All of these log `myObj`.g();f.bind(myObj)();f.call(myObj);h(g);
class Demo{a = this;b(){return this;}static c = this;static d(){return this;}// Getters, setters, private modifiers are also possible.}
const demo = new Demo;
console.log(demo.a, demo.b()); // Both log `demo`.console.log(Demo.c, Demo.d()); // Both log `Demo`.
if(true){console.log(this); // What is `this` here?}
globalThis。标记的行在初始全局执行上下文中进行评估。
const obj = {};
function myFun(){return { // What is `this` here?"is obj": this === obj,"is globalThis": this === globalThis};}
obj.method = myFun;
console.log(obj.method());
function myFun() {// What is `this` here?return {"is obj": this === obj,"is globalThis": this === globalThis};}
const obj = {};
console.log(myFun.call(obj));
class MyCls{arrow = () => ({ // What is `this` here?"is MyCls": this === MyCls,"is globalThis": this === globalThis,"is instance": this instanceof MyCls});}
console.log(new MyCls().arrow());
/*********************************************************************1. When you add variable to the function using this keyword, itgets added to the function prototype, thus allowing all functioninstances to have their own copy of the variables added.*********************************************************************/function functionDef(){this.name = "ObjDefinition";this.getName = function(){return this+":"+this.name;}}
obj1 = new functionDef();document.write(obj1.getName() + "<br />"); //[object Object]:ObjDefinition
/*********************************************************************2. Members explicitly added to the function protorype also behaveas above: all function instances have their own copy of thevariable added.*********************************************************************/functionDef.prototype.version = 1;functionDef.prototype.getVersion = function(){return "v"+this.version; //see how this.version refers to the//version variable added through//prototype}document.write(obj1.getVersion() + "<br />"); //v1
/*********************************************************************3. Illustrating that the function variables added by both aboveways have their own copies across function instances*********************************************************************/functionDef.prototype.incrementVersion = function(){this.version = this.version + 1;}var obj2 = new functionDef();document.write(obj2.getVersion() + "<br />"); //v1
obj2.incrementVersion(); //incrementing version in obj2//does not affect obj1 version
document.write(obj2.getVersion() + "<br />"); //v2document.write(obj1.getVersion() + "<br />"); //v1
/*********************************************************************4. `this` keyword refers to the immediate parent object. If younest the object through function prototype, then `this` insideobject refers to the nested object not the function instance*********************************************************************/functionDef.prototype.nestedObj = { name: 'nestedObj',getName1 : function(){return this+":"+this.name;}};
document.write(obj2.nestedObj.getName1() + "<br />"); //[object Object]:nestedObj
/*********************************************************************5. If the method is on an object's prototype chain, `this` refersto the object the method was called on, as if the method was onthe object.*********************************************************************/var ProtoObj = { fun: function () { return this.a } };var obj3 = Object.create(ProtoObj); //creating an object setting ProtoObj//as its prototypeobj3.a = 999; //adding instance member to obj3document.write(obj3.fun()+"<br />");//999//calling obj3.fun() makes//ProtoObj.fun() to access obj3.a as//if fun() is defined on obj3
4.在构造函数内部使用时
当函数用作构造函数时(即用new关键字调用它时),函数体中的this指向正在构造的新对象。
var myname = "global context";function SimpleFun(){this.myname = "simple function";}
var obj1 = new SimpleFun(); //adds myname to obj1//1. `new` causes `this` inside the SimpleFun() to point to the// object being constructed thus adding any member// created inside SimipleFun() using this.membername to the// object being constructed//2. And by default `new` makes function to return newly// constructed object if no explicit return value is specified
document.write(obj1.myname); //simple function
var ProtoObj = {fun: function () {return this.a;}};//Object.create() creates object with ProtoObj as its//prototype and assigns it to obj3, thus making fun()//to be the method on its prototype chain
var obj3 = Object.create(ProtoObj);obj3.a = 999;document.write(obj3.fun()); //999
//Notice that fun() is defined on obj3's prototype but//`this.a` inside fun() retrieves obj3.a
var status = 1;var helper = {status : 2,getStatus: function () {return this.status;}};
var theStatus1 = helper.getStatus(); //line1console.log(theStatus1); //2
var theStatus2 = helper.getStatus;console.log(theStatus2()); //1
function Person(name){this.personName = name;this.sayHello = function(){return "Hello " + this.personName;}}
var person1 = new Person('Scott');console.log(person1.sayHello()); //Hello Scott
var person2 = new Person('Hugh');var sayHelloP2 = person2.sayHello;console.log(sayHelloP2()); //Hello undefined
// continuing with the previous code snippet
var myVar = myObj.logThis;myVar();// logs either of window/global/undefined based on mode of operation
考虑一个更常见的实际场景:
var el = document.getElementById('idOfEl');el.addEventListener('click', function() { console.log(this) });// the function called by addEventListener contains this as the reference to the element// so clicking on our element would log that element itself
new关键字
考虑Javascript中的构造函数:
function Person (name) {this.name = name;this.sayHello = function () {console.log ("Hello", this);}}
var awal = new Person("Awal");awal.sayHello();// In `awal.sayHello`, `this` contains the reference to the variable `awal`
var myObj = {hello: function () {return "world"},myMethod: function () {// copy this, variable names are case-sensitivevar that = this;// callbacks ftw \o/foo.bar("args", function () {// I want to call `hello` herethis.hello(); // error// but `this` references to `foo` damn!// oh wait we have a backup \o/that.hello(); // "world"});}};
var person = {firstName: "Penelope",lastName: "Barrymore",fullName: function () {
// We use "this" just as in the sentence above:console.log(this.firstName + " " + this.lastName);
// We could have also written:console.log(person.firstName + " " + person.lastName);}}
function foo() {// return an arrow functionreturn (a) => {// `this` here is lexically inherited from `foo()`console.log(this.a);};}var obj1 = { a: 2 };var obj2 = { a: 3 };
var bar = foo.call(obj1);bar.call( obj2 ); // 2, not 3!
Except in the case of DOM event handlers or when a thisArg is provided (see further down), both in node and in a browser using this in a function that is not called with new references the global scope…
function Thing() {this.things = [];}
var thing1 = new Thing();var thing2 = new Thing();thing1.things.push("foo");console.log(thing1.things); //logs ["foo"]console.log(thing2.things); //logs []
反对这
您可以在对象的任何函数中使用this来引用该对象的其他属性。这与使用new创建的实例不同。
var obj = {foo: "bar",logFoo: function () {console.log(this.foo);}};
obj.logFoo(); //logs "bar"
DOM事件
在超文本标记语言DOM事件处理程序中,this始终是对事件附加到的DOM元素的引用
function Listener() {document.getElementById("foo").addEventListener("click",this.handleClick);}Listener.prototype.handleClick = function (event) {console.log(this); //logs "<div id="foo"></div>"}
var listener = new Listener();document.getElementById("foo").click();
除非你是bind
function Listener() {document.getElementById("foo").addEventListener("click",this.handleClick.bind(this));}Listener.prototype.handleClick = function (event) {console.log(this); //logs Listener {handleClick: function}}
var listener = new Listener();document.getElementById("foo").click();
function Thing () {}Thing.prototype.foo = "bar";Thing.prototype.logFoo = function () {eval("console.log(this.foo)"); //logs "bar"}
var thing = new Thing();thing.logFoo();
与此
您可以使用with将this添加到当前范围以读取和写入this上的值,而无需显式引用this。
function Thing () {}Thing.prototype.foo = "bar";Thing.prototype.logFoo = function () {with (this) {console.log(foo);foo = "foo";}}
var thing = new Thing();thing.logFoo(); // logs "bar"console.log(thing.foo); // logs "foo"
function UserDefinedFunction(){alert(this.a + "," + this.b + "," + this.c + "," + this.d)}var o1={a:1,b:2,f:UserDefinedFunction,bf:null}var o2={c:3,d:4,f:UserDefinedFunction,bf:null}
var bound1=UserDefinedFunction.bind(o1); // permanantly fixes "this" value of function "bound1" to Object o1bound1() // Shall display 1,2,undefined,undefined
var bound2=UserDefinedFunction.bind(o2); // permanantly fixes "this" value of function "bound2" to Object o2bound2() // Shall display undefined,undefined,3,4
var bound3=o1.f.bind(o2); // permanantly fixes "this" value of function "bound3" to Object o2bound3() // Shall display undefined,undefined,3,4
var bound4=o2.f.bind(o1); // permanantly fixes "this" value of function "bound4" to Object o1bound4() // Shall display 1,2,undefined,undefined
o1.bf=UserDefinedFunction.bind(o2) // permanantly fixes "this" value of function "o1.bf" to Object o2o1.bf() // Shall display undefined,undefined,3,4
o2.bf=UserDefinedFunction.bind(o1) // permanantly fixes "this" value of function "o2.bf" to Object o1o2.bf() // Shall display 1,2,undefined,undefined
bound1.call(o2) // Shall still display 1,2,undefined,undefined. "call" cannot alter the value of "this" for bound function
bound1.apply(o2) // Shall still display 1,2,undefined,undefined. "apply" cannot alter the value of "this" for bound function
o2.bf.call(o2) // Shall still display 1,2,undefined,undefined. "call" cannot alter the value of "this" for bound functiono2.bf.apply(o2) // Shall still display 1,2,undefined,undefined."apply" cannot alter the value of "this" for bound function
function Car(make, model, year) {var this = {}; // under the hood, so to speakthis.make = make;this.model = model;this.year = year;return this; // under the hood}
var mycar = new Car('Eagle', 'Talon TSi', 1993);// ========= under the hoodvar this = {};this.make = 'Eagle';this.model = 'Talon TSi';this.year = 1993;return this;
let object = {prop1: function () {console.log(this);}}
object.prop1(); // object is left of the dot, thus this is object
const myFunction = object.prop1 // We store the function in the variable myFunction
myFunction(); // Here we are in the global space// myFunction is a property on the global object// Therefore it logs the window object
事件监听器示例:
document.querySelector('.foo').addEventListener('click', function () {console.log(this); // This refers to the DOM element the eventListener was invoked from})
document.querySelector('.foo').addEventListener('click', () => {console.log(this); // Tip, es6 arrow function don't have their own binding to the this v}) // Therefore this will log the global object
.foo:hover {color: red;cursor: pointer;}
<div class="foo">click me</div>
Example constructor:
function Person (name) {this.name = name;}
const me = new Person('Willem');// When using the new keyword the this in the constructor function will refer to the newly created object
console.log(me.name);// Therefore, the name property was placed on the object created with new keyword.
const bar = {name: 'bar',fn1() { console.log(this); },fn2: function() { console.log(this); },fn3: otherFunction,};
function otherFunction() { console.log(this) };
bar.fn1(); // this is barbar.fn2(); // this is barbar.fn3(); // this is bar
function foo() {console.log(this);}
const bar = foo.bind({name: 'moo'});
// bind created a new invisible function that calls foo with the bound object.
bar();
// the objectForThis we are passing to bar here is ignored because// the invisible function that bind created will call foo with with// the object we bound above
bar.call({name: 'other'});
请注意,如果functionObject.bind不存在,我们可以像这样制作自己的
function bind(fn, objectForThis) {return function(...args) {return fn.call(objectForthis, ...args);};}
然后我们可以这样称呼它
function foo() {console.log(this);}
const bar = bind(foo, {name:'abc'});
箭头函数,=>运算符是bind的语法糖
const a = () => {console.log(this)};
与
const tempFn = function() {console.log(this)};const a = tempFn.bind(this);
function foo() {function tempFn() {console.log(this);}return tempFn.bind(this);}
const obj = {foo,};const b = obj.foo();b.call(window or undefined if strict mode);
<body><button class="btn">Click Me</button><script>function printMe(){//Terminal2: this function declared inside window context so this function belongs to the window object.console.log(this);}document.querySelector('.btn').addEventListener('click', function(){//Terminal1: button context, this callback function belongs to DOM elementconsole.log(this);printMe();})</script></body>
输出:有意义吗?(阅读评论)
如果您无法理解上面的示例,让我们尝试使用我们自己的回调;
<script>var myObj = {firstName:"Lord",lastName:'Baron',printName:function(callback1, callback2){//Attaching callback1 with this myObj contextthis.callback1 = callback1;this.callback1(this.firstName +" "+this.lastName)//We did not attached callback2 with myObj so, it's reamin with window context by defaultcallback2();/*//test bellow codesthis.callback2 = callback2;this.callback2();*/}}var callback2 = function (){console.log(this);}myObj.printName(function(data){console.log(data);console.log(this);}, callback2);</script>
输出:
现在让我们了解范围,自我,生活以及这是如何表现的
var color = 'red'; // property of windowvar obj = {color:'blue', // property of windowprintColor: function(){ // property of obj, attached with objvar self = this;console.log('In printColor -- this.color: '+this.color);console.log('In printColor -- self.color: '+self.color);(function(){ // decleard inside of printColor but not property of object, it will executed on window context.console.log(this)console.log('In IIFE -- this.color: '+this.color);console.log('In IIFE -- self.color: '+self.color);})();
function nestedFunc(){// decleard inside of printColor but not property of object, it will executed on window context.console.log('nested fun -- this.color: '+this.color);console.log('nested fun -- self.color: '+self.color);}
nestedFunc(); // executed on window contextreturn nestedFunc;}};
obj.printColor()(); // returned function executed on window context</script>