이번 글에서는 특정 참조값을 가지고 있는 this 객체를 주로 소개하고 있습니다. 도움이 필요한 친구들이 참고할 수 있도록 하겠습니다.
이를 활용하기 위해 저희는 일반적으로 접하게 되는 것은 전역 함수, 개체 메서드, 호출 및 적용, 클로저, 화살표 함수 및 클래스에서
우리는 이 개체가 함수의 실행 환경에 바인딩되어 있음을 알고 있습니다. 이 값은 함수가 호출되기 전에 결정되지 않으므로 코드 실행 중에 다른 개체를 참조합니다. 어떤 객체 인스턴스가 이것이 위치한 함수를 호출하는지, 이는 어떤 객체 인스턴스를 나타냅니다.
1. Global function
전역 함수에서는 window #🎜🎜와 같습니다. ## 🎜🎜#
var name = "Tina";function sayName() { alert(this.name); } person();//Tina
여기서 person() 함수는 글로벌 환경에서 실행되기 때문에, window 객체에서 호출한 person()이기도 합니다. 따라서 전역 범위는 현재 창 개체를 가리킵니다. 이 함수가 객체 o에 할당되고 o.sayName()이 호출되면 this는 객체 o를 참조하므로 this.name의 평가는 o.name의 평가가 됩니다.
name = "Tina"
2. 객체 메서드# 🎜🎜#
함수가 객체의 메서드로 호출되는 경우 이는 해당 객체와 동일합니다.
var name="Tina";var obj={ name="Tony", getName: function() { alert(this.name); } }; obj.getName();//"Tony"
call(ctx, parm1,parm2,parm3...) 및 apply(ctx,[parms])의 목적은 특정 범위에서 함수를 호출하는 것입니다. 이는 실제로 이 개체의 값을 function body; #🎜🎜 #
function sum(num1, num2) { return num1+num2; }function callSum1(num1, num2) { return sum.apply(this, [num1, num2]); }function callSum2(num1,num2) { return sum.call(this, num1, num2); } alert(callSum1(10, 10)); //20alert(callSum2(10, 10));//20
window.color="red";var o={ color: "blue"};function sayColor() { alert(this.color); } sayColor();//"red"sayColor.call(this);//"red"sayColor.call(window);//"red"sayColor.call(o);//"blue"
바인딩() 메서드는 함수의 인스턴스를 생성하고 해당 this 값은 값에 바인딩됩니다. 바인딩() 함수에 전달됩니다. 예:
window.color="red";var o={ color: "blue" };function sayColor() { alert(this.color); }var objsayColor = sayColor.bind(o); objsayColor();//"blue"
또 다른 사용 시나리오는 함수 바인딩입니다. 함수 바인딩을 사용하려면 특정 환경에서 사용할 수 있는 함수를 만들어야 합니다. 지정된 매개변수를 사용하여 다른 함수를 호출합니다. 이 기술은 함수를 변수로 전달하는 동안 코드 실행 환경을 유지하기 위해 콜백 함수 및 이벤트 핸들러와 함께 자주 사용됩니다.
var handler = { message: "Event handled", handleClick : function(event) { alert(this.message); } };var btn = document.getElementById("my_btn"); btn.addEventListener("click", handler.handleClick, false);
버튼을 누르면 함수가 호출되어 경고박스가 나와야 할 것 같은데 경고박스가 뜹니다 이벤트가 처리되었지만 실제로 표시되는 내용은 정의되지 않았습니다. 그 이유는 handler.handleClick()의 실행 환경이 저장되지 않기 때문에 this 객체는 최종적으로 핸들러 대신 DOM 버튼을 가리키게 됩니다(IE8에서는 이것이 창을 가리킵니다). 이 문제를 해결하는 한 가지 방법은 클로저를 사용하는 것입니다.
var handler = { message: "Event handled", handleClick : function(event) { alert(this.message); } };var btn = document.getElementById("my_btn"); btn.addEventListener("click", function(event){ handler.handleClick(event); }, false);
이 솔루션은 onclick 이벤트 핸들러 내의 클로저를 사용하여 handler.handleClick()을 직접 호출합니다. 이 코드 조각과 관련된 솔루션입니다. 클로저를 여러 개 생성하면 코드를 이해하고 디버깅하기가 어려워질 수 있다는 것을 알고 있습니다. 따라서 많은 JS 라이브러리는 특정 환경에 함수를 바인딩할 수 있는 함수를 구현합니다. 일반적으로 이 함수는 bind()라고 하며, ECMAScript 5에서는 모든 함수에 대한 기본 바인딩() 메서드를 정의하며 그 사용 방법은 다음과 같습니다. #
var handler = { message: "Event handled", handleClick : function(event) { alert(this.message+":"+event.type); } };var btn = document.getElementById("my_btn"); btn.addEventListenr("click", handler.handleClick.bind(handler), false);
function bind(fn, context) { return function() { return fn.apply(context, arguments); }; }
4. Closure
때로는 클로저 작성 방법이 다르기 때문에 이 객체가 클로저에 사용됩니다. 문제;
var name = "The window";var object = { name: "My Object", getNameFunc: function() { return function() { return this.name; }; } }; alert(object.getNameFunc()());//"The window"
由于getNameFunc()返回一个函数,因此调用object.getNameFunc()()就会立即调用它返回的函数,结果就是返回一个字符串"The window",即全局变量的值,此时匿名函数没有取得其包含作用域(外部作用域)的this对象。原因在于内部函数在搜索两个特殊变量this和arguments时,只会搜索到其活动对象为止,因此永远不可能直接访问外部函数中的这两个变量。这时,只需把把外部作用域中的this对象保存在一个闭包能够访问到的变量里,就可以让闭包访问该对象了。
var name = "The window";var object = { name: "My Object", getNameFunc: function() { var that = this; return function() { return that.name; }; } }; alert(object.getNameFunc()());//"My Object"
//节流function throttle(fn, delay) { var previous = Data.now(); return function() { var ctx = this; var args = arguments; var now = Data.now(); var diff = now-previous-delay; if(diff>=0) { previous = now; setTimeout(function() { fn.apply(ctx, args); }, delay); } }; }
5. 箭头函数
我们知道,箭头函数有几个需要注意的点:
(1)函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象;
(2)不可以当作构造函数,也就是说,不可以使用new命令,否则会抛出一个错误;
(3)不可以使用arguments对象,该对象在函数体内不存在。如果要用,可以用rest参数代替;
(4)不可以使用yield命令,因此箭头函数不能用作Generator函数;
这里我们只谈论第一点;this对象的指向是可变的,但在箭头函数中,它是固定的;
function foo() { setTimeout(() => { console.log('id: ', this.id); }, 100); }var id=21; foo.call({id: 31});//id: 31
上述代码中,setTimeout是一个箭头函数,这个箭头函数的定义生效是在foo函数生成时,而它真正加入到执行栈后还要等到100毫秒后才会执行,如果是普通函数,此时的this应该指向全局对象window,这时应该输出21。但是,箭头函数导致this总是指向函数定义生效时所在的对象(本例是{id:31})所以输出的是id: 31;
箭头函数可以让setTimeout里面的this,绑定定义时所在的作用域,而不是指向运行时所在的作用域。下面是另一个例子:
function Timer() { this.s1 = 0; this.s2 = 0; setInterval(() => this.s1++, 1000); setInterval(function() { this.s2++; }, 1000); }var timer = new Timer(); setTimeout(() => console.log('s1: ', timer.s1), 3100);//s1: 3setTimeout(() => console.log('s2: ', timer.s2), 3100);//s2: 0
上面代码中,Timer函数内部设置了两个定时器,分别使用了箭头函数和普通函数。前者的this绑定定义时所在的作用域(Timer函数),后者的this指向运行时所在的作用域(即全局对象)。所以,3100毫秒后,timer.s1被更新了3次,timer.s2一次都没更新。
箭头函数可以让this指向固定化,这种特性很有利于封装回调函数。下面代码将DOM事件的回调函数封装在一个对象里面。
var handler = { id: '123456', init: function() { document.addEventListener('click', event => this.doSomething(event.type), false); }, doSomething: funcition(type) { console.log('Handling ' + type + ' for ' + this.id); } };
上面代码的init方法中,使用了箭头函数,这导致这个箭头函数里面的this,总是指向handler对象。否则,回调函数运行时,this.doSomething这一行会报错,因为此时this指向document对象。this指向的固定化,并不是因为箭头函数内部有绑定this的机制,实际原因是箭头函数根本没有自己的this,导致内部的this就是外层代码的this。正是因为它没有this,所以也就不能用作构造函数。由于箭头函数没有自己的this,所以当然不能用call()、apply()、bind()改变this的指向。
6. class
类的方法内部如果含有this,它默认指向类的实例。
class Logger { /*constructor() { this.printName = this.printName.bind(this); }*/ printName(name = 'Nicolas') { this.print(`Hello ${name}`); } print(text) { console.log(text); } } const logger = new Logger(); const { printName } = logger; printName();
上面代码中,printName方法中的this,默认指向Logger类的实例。但是,如果将这个方法提取出来单独使用,this会指向该方法运行时所在的环境,因为找不到print方法而导致报错。一种简单的解决方法就是在构造函数中绑定this。而另一种方法是使用箭头函数:
class Logger { constructor() { this.printName = (name='Nicolas') => { this.print(`Hello ${name}`); } print(text) { console.log(text); } } const logger = new Logger(); const { printName } = logger; printName();
还有一种方法是使用Proxy,获取方法的时候,自动绑定this。
function selfish (target) { const cache = new WeakMap(); const handler = { get (target, key) { const value = Reflect.get(target, key); if (typeof value !== 'function') { return value; } if (!cache.has(value)) { cache.set(value, value.bind(target)); } return cache.get(value); } }; const proxy = new Proxy(target, handler); return proxy; } const logger = selfish(new Logger());
以上就是本文的全部内容,希望对大家的学习有所帮助,更多相关内容请关注PHP中文网!
相关推荐:
위 내용은 자바스크립트에서 이 객체의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!