* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* * * * * * * * * * * *) * * * * * * * * * * *1004* * * * *равно "undefined", если:
- Метод / функция были привязаны к
object
с ES5 bind(this)
(см. примечание ниже) ИЛИ отскок за пределы object
путем повторного связывания внешней функции сobject
сам по себе: bind(obj)
.
Примечание : Как показано ниже (в методе 6), есть исключение при использовании ES5 arrow functions
внутри object
означает, что он сохранит вмещающую лексическую область this
без необходимости быть связанным.
Например:
this.prop = "global prop"
const outsideArrowFunction = () => (this.prop)
function outsideFunction() {
return this.prop;
};
const obj = {
prop: "obj's prop",
method: function() {
return this.prop; // returns "obj's prop"
},
method2: function() {
return this; // returns the entire "obj" and its properties
},
method3: function() {
return this.method(); // returns "obj's prop"
},
method4: function() {
return outsideFunction(); // returns "global prop" because the outsideFunction's lexical scope doesn't recognize the "obj"'s nor its properties
},
method5: function() {
return outsideArrowFunction(); // same as method4, utilizes global this
},
method6: function() {
const x = () => this.method();
return x(); // returns "obj's prop" because arrow functions take on "this" from the "obj"
},
method7: function() {
const x = function() {
return this.prop;
};
return x(); // returns "global prop" because "this" loses lexical scope upon execution
},
method8: function() {
const x = this.method.bind(this);
return x(); // returns "obj's prop" because "this" refers to the "obj" upon execution
},
method9: function(callback) {
return callback(this.method);
},
method10: function() {
return this.method9(function(callback) {
return callback(); // returns "global prop" because "this" loses lexical scope upon execution
});
}
};
const a = outsideArrowFunction.bind(obj); // returns "global prop" because arrow functions take on whatever "this" is upon its creation, so "this" refers to the global "this"
const b = outsideFunction.bind(obj); // returns "obj's prop" since a traditional function can rebind "this", which has been rebound to "obj"
console.log(`Method: ${obj.method()}`);
console.log(`Method2: ${obj.method2()}`);
console.log(`Method3: ${obj.method3()}`);
console.log(`Method4: ${obj.method4()}`);
console.log(`Method5: ${obj.method5()}`);
console.log(`Method6: ${obj.method6()}`);
console.log(`Method7: ${obj.method7()}`);
console.log(`Method8: ${obj.method8()}`);
console.log(`Method10: ${obj.method10()}`);
console.log(`arrowFunction: ${a()}`);
console.log(`outsideFunction: ${b()}`);
Когда дело доходит до classes
, это шаблон objects
.Таким образом, this
будет undefined
или глобальным this
, если класс method
не связан в constructor
или вы не используете arrow function
.Попробуйте приведенный ниже пример, нажав на каждую из кнопок, обратите внимание на то, как все 3 метода могут работать, но зависит от того, как они назывались :
class Example extends React.Component {
constructor() {
super();
this.state = { method: "" };
this.boundMethod = this.boundMethod.bind(this);
}
componentDidMount() {
this.unboundMethod();
};
boundMethod() {
this.setState({ method: "Bound Method" }); // this works because the method is bound to the class
}
unboundMethod() {
try {
this.setState({ method: "Unbound Method" }); // this only works if it's called within a bound method class (like componentDidMount)
} catch (err) {
alert(err); // however, if it's called within a callback (like in an onClick event), it fails.
}
}
arrowMethod = () => {
this.setState({ method: "Arrow Method" }); // this works because arrow methods are automatically bound to the class
};
render() {
return (
<div>
<button onClick={this.boundMethod}>Bound Method</button>
<button onClick={this.unboundMethod}>Unbound Method</button>
<button onClick={this.arrowMethod}>Arrow Method</button>
<p>The {this.state.method} was called</p>
</div>
);
};
}
ReactDOM.render(<Example />, document.body);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>