bind() 함수는 호출된 함수(바운드 함수의 대상 함수)와 동일한 함수 본문(ECMAScript 5 사양의 내장 호출 속성)을 갖는 새 함수(바운드 함수라고 함)를 생성합니다. . 대상 함수가 호출되면 this 값은 바인딩()의 첫 번째 매개변수에 바인딩되며 재정의될 수 없습니다. 바인딩된 함수가 호출되면 바인딩()은 원래 함수에 제공하기 위해 미리 설정된 매개변수도 허용합니다. 바인딩된 함수는 new 연산자를 사용하여 객체를 생성할 수도 있습니다. 이는 생성자로서 원래 함수처럼 동작합니다. 제공된 이 값은 무시되고 호출에 대한 인수는 모의 함수에 제공됩니다.
자바스크립트의 범위는 실행되는 환경에 따라 결정되기 때문에 함수 정의가 실제로 실행되는 환경과 다른 경우가 많고 이에 따라 범위도 변경됩니다.
예를 들어 다음과 같은 상황입니다.
var id = 'window'; //定义一个函数,但是不立即执行 var test = function(){ console.log(this.id) } test() // window //把test作为参数传递 var obj = { id:'obj', hehe:test } //此时test函数运行环境发生了改变 obj.hehe() // 'obj' //为了避免这种情况,javascript里面有一个bind方法可以在函数运行之前就绑定其作用域,修改如下 var id = 'window'; var test = function(){ console.log(this.id) }.bind(window) var obj = { id:'obj', hehe:test } test() // window obj.hehe() // window
위에서 소개한 것처럼 바인딩 메소드의 중요한 역할은 범위를 함수에 바인딩하는 것입니다. 그러나 바인드 메소드는 하위 버전과 호환되지 않습니다. 브라우저에서 수동으로 구현할 수 있습니다.
핵심 아이디어 분할
bind 메소드는 함수를 바로 실행하지 않기 때문에 실행할 함수를 반환해야 한다(여기서는 클로저를 사용하고, 함수를 반환할 수 있음) return function(){ }
범위 바인딩, 여기서는 apply 또는 call 메서드를 사용하여 xx.call(yy)/xx.apply(yy)
매개변수 전달을 구현할 수 있습니다. 매개변수의 불확실성, 배열을 전달하려면 적용을 사용해야 합니다(예제는 더 명확합니다). xx.apply(yy,[...Array...]). 호출을 사용하면 편리하지 않습니다. 호출은 하나씩 나열되어야 합니다
구현
위의 아이디어로 대략적인 프로토타입은 이미 명확하고 코드는 구현하기 쉬워야 합니다
바인드 범위 , 바인드 매개변수 전송
Function.prototype.testBind = function(that){ var _this = this, /* *由于参数的不确定性,统一用arguments来处理,这里的arguments只是一个类数组对象,有length属性 *可以用数组的slice方法转化成标准格式数组,除了作用域对象that以外, *后面的所有参数都需要作为数组参数传递 *Array.prototype.slice.apply(arguments,[1])/Array.prototype.slice.call(arguments,1) */ slice = Array.prototype.slice, args = slice.apply(arguments,[1]); //返回函数 return function(){ //apply绑定作用域,进行参数传递 return _this.apply(that,args) } }
테스트
var test = function(a,b){ console.log('作用域绑定 '+ this.value) console.log('testBind参数传递 '+ a.value2) console.log('调用参数传递 ' + b) }var obj = { value:'ok'}var fun_new = test.testBind(obj,{value2:'also ok'}) fun_new ('hello bind')// 作用域绑定 ok// testBind参数传递 also ok// 调用参数传递 undefined
동적 매개변수
바인드 메소드의 범위 바인딩은 위에서 구현했지만 연고에 파리는 함수를 반환하므로 매개변수 전달을 호출할 때 지원되어야 합니다. 분명히 위의 fun_new는 호출 시 매개변수 전달을 지원하지 않으며 testBind가 바인딩될 때만 매개변수를 전달할 수 있습니다. 왜냐하면 우리가 호출하게 되는 것은 이 반환 함수입니다. 🎜>
function(){ return _this.apply(that,args) } 这里面的args在绑定的时候就已经确定了,调用的时候值已经固定, 我们并没有处理这个function传递的参数。변환합니다
return function(){ return _this.apply(that, args.concat(Array.prototype.slice.apply(arguments,[0])) ) }Array.prototype.slice.apply(arguments,[0]) 여기서는 반환 함수가 실행될 때 전달되는 일련의 매개 변수를 참조하므로 첫 번째 매개변수 [0]부터 시작하고, 이전 args = Slice.apply(arguments,[1]) 은 testBind 메서드가 실행될 때 전달된 매개변수를 참조하므로 두 번째 매개변수 [1]부터 시작하면 두 개는 본질적으로 서로 다르며 혼동될 수 없습니다. 둘이 병합된 후에만 반환된 함수의 전체 매개변수가 이므로 다음과 같은 구현이 있습니다.
Function.prototype.testBind = function(that){ var _this = this, slice = Array.prototype.slice, args = slice.apply(arguments,[1]); return function(){ return _this.apply(that, args.concat(Array.prototype.slice.apply(arguments,[0])) ) } }Test
var test = function(a,b){ console.log('作用域绑定 '+ this.value) console.log('testBind参数传递 '+ a.value2) console.log('调用参数传递 ' + b) } var obj = { value:'ok' } var fun_new = test.testBind(obj,{value2:'also ok'}) fun_new ('hello bind') // 作用域绑定 ok // testBind参数传递 also ok // 调用参数传递 hello bind위의 두 가지 매개변수 전달 방법에서는 args.concat(Array.prototype.slice.apply(arguments,[0]))에서 알 수 있듯이 바인드의 우선순위가 높으며 바인드의 매개변수가 앞에 있습니다. 배열의. 프로토타입 체인공식 문서에 다음 문장이 있습니다:
A bound function may also be constructed using the new operator: doing so acts as though the target function had instead been constructed. The provided this value is ignored, while prepended arguments are provided to the emulated function.바운드 함수가 new에 의해 인스턴스화되면 프로토타입을 상속해야 함을 의미합니다. 원래 함수의 chain 메소드를 사용하고 바인딩 프로세스 중에 제공된 this는 무시되지만(원래 함수의 this 객체는 상속됨) 매개변수는 계속 사용됩니다.
여기서 프로토타입 체인을 전달하려면 전달 함수가 필요합니다.
fNOP = function () {} //创建一个中转函数 fNOP.prototype = this.prototype; xx.prototype = new fNOP() 修改如下 Function.prototype.testBind = function(that){ var _this = this, slice = Array.prototype.slice, args = slice.apply(arguments,[1]), fNOP = function () {}, //所以调用官方bind方法之后 有一个name属性值为 'bound ' bound = function(){ return _this.apply(that, args.concat(Array.prototype.slice.apply(arguments,[0])) ) } fNOP.prototype = _this.prototype; bound.prototype = new fNOP(); return bound; }바인드 메소드의 첫 번째 매개변수인 this는 전달해야 하는 두 가지 상황이 있습니다. 직접바인드 호출 후 메소드
var f = function () { console.log('不传默认为'+this) };f.bind()() // 不传默认为 Window로 나누어지므로 바인딩 메소드를 직접 호출할 경우 Apply(즉, Apply(that||window,)로 변경하는 것이 좋습니다. 실제로 변경하지 않아도 괜찮습니다. 통과하지 않으면 기본 지점은 windownew를 사용하여 바운드 메서드 인스턴스화가 혼동되기 쉽습니다. new를 사용할 때 표준 바인드 메소드가 무엇을 하는지 파악한 다음 이를 명확하게 구현할 수 있습니다 여기서는 new 메소드가 어떤 작업을 수행하는지 확인해야 합니다. 예를 들어 var a = new b() 은 빈 객체 a = {}를 생성하고 이 변수 참조는 이 빈 객체 a를 가리킵니다.인스턴스화된 함수의 프로토타입 상속: a.__proto__ = b.prototype
被实例化方法b的this对象的属性和方法将被加入到这个新的 this 引用的对象中: b的属性和方法被加入的 a里面
新创建的对象由 this 所引用 :b.call(a)
通过以上可以得知,如果是var after_new = new bindFun(); 由于这种行为是把原函数当成构造器,那么那么最终实例化之后的对象 this需要继承自原函数, 而这里的 bindFun 目前是
function(){ return _this.apply(that || window, args.concat(Array.prototype.slice.apply(arguments,[0])) ) }
这里apply的作用域是绑定的that || window,在执行 testBind()的时候就已经固定,并没有把原函数的this对象继承过来,不符合我们的要求,我们需要根据apply的特性解决这个问题:
在一个子构造函数中,你可以通过调用父构造函数的 `apply/call` 方法来实现继承
例如
function Product(name, price) { this.name = name; this.price = price; if (price < 0) { throw RangeError('Cannot create product ' + this.name + ' with a negative price'); } } function Food(name, price) { Product.call(this, name, price); this.category = 'food'; } //等同于(其实就是把Product放在Food内部执行了一次) function Food(name, price) { this.name = name; this.price = price; if (price < 0) { throw RangeError('Cannot create product ' + this.name + ' with a negative price'); } this.category = 'food'; }
所以在new新的实例的时候实时将这个新的this对象 进行 apply 继承原函数的 this 对象,就可以达到 new 方法里面的第 3 步的结果
apply(that||window, //修改为 如果是new的情况,需要绑定new之后的作用域,this指向新的实例对象 apply(isNew ? this : that||window, ==> Function.prototype.testBind = function(that){ var _this = this, slice = Array.prototype.slice, args = slice.apply(arguments,[1]), fNOP = function () {}, //所以调用官方bind方法之后 有一个name属性值为 'bound ' bound = function(){ return _this.apply(isNew ? this : that||window, args.concat(Array.prototype.slice.apply(arguments,[0])) ) } fNOP.prototype = _this.prototype; bound.prototype = new fNOP(); return bound; }
这里的 isNew 是区分 bindFun 是直接调用还是被 new 之后再调用,通过原型链的继承关系可以知道,
bindFun 属于 after_new的父类,所以 after_new instanceof bindFun 为 true,同时
bindFun.prototype = new fNOP() 原型继承; 所以 fNOP 也是 after_new的父类, after_new instanceof fNOP 为 true
最终结果
Function.prototype.testBind = function(that){ var _this = this, slice = Array.prototype.slice, args = slice.apply(arguments,[1]), fNOP = function () {}, bound = function(){ //这里的this指的是调用时候的环境 return _this.apply(this instanceof fNOP ? this : that||window, args.concat(Array.prototype.slice.apply(arguments,[0])) ) } fNOP.prototype = _this.prototype; bound.prototype = new fNOP(); return bound; }
我看到有些地方写的是
this instanceof fNOP && that ? this : that || window,
我个人觉得这里有点不正确,如果绑定时候不传参数,那么that就为空,那无论怎样就只能绑定 window作用域了。

실제 세계에서 JavaScript의 응용 프로그램에는 프론트 엔드 및 백엔드 개발이 포함됩니다. 1) DOM 운영 및 이벤트 처리와 관련된 TODO 목록 응용 프로그램을 구축하여 프론트 엔드 애플리케이션을 표시합니다. 2) Node.js를 통해 RESTFULAPI를 구축하고 Express를 통해 백엔드 응용 프로그램을 시연하십시오.

웹 개발에서 JavaScript의 주요 용도에는 클라이언트 상호 작용, 양식 검증 및 비동기 통신이 포함됩니다. 1) DOM 운영을 통한 동적 컨텐츠 업데이트 및 사용자 상호 작용; 2) 사용자가 사용자 경험을 향상시키기 위해 데이터를 제출하기 전에 클라이언트 확인이 수행됩니다. 3) 서버와의 진실한 통신은 Ajax 기술을 통해 달성됩니다.

보다 효율적인 코드를 작성하고 성능 병목 현상 및 최적화 전략을 이해하는 데 도움이되기 때문에 JavaScript 엔진이 내부적으로 작동하는 방식을 이해하는 것은 개발자에게 중요합니다. 1) 엔진의 워크 플로에는 구문 분석, 컴파일 및 실행; 2) 실행 프로세스 중에 엔진은 인라인 캐시 및 숨겨진 클래스와 같은 동적 최적화를 수행합니다. 3) 모범 사례에는 글로벌 변수를 피하고 루프 최적화, Const 및 Lets 사용 및 과도한 폐쇄 사용을 피하는 것이 포함됩니다.

Python은 부드러운 학습 곡선과 간결한 구문으로 초보자에게 더 적합합니다. JavaScript는 가파른 학습 곡선과 유연한 구문으로 프론트 엔드 개발에 적합합니다. 1. Python Syntax는 직관적이며 데이터 과학 및 백엔드 개발에 적합합니다. 2. JavaScript는 유연하며 프론트 엔드 및 서버 측 프로그래밍에서 널리 사용됩니다.

Python과 JavaScript는 커뮤니티, 라이브러리 및 리소스 측면에서 고유 한 장점과 단점이 있습니다. 1) Python 커뮤니티는 친절하고 초보자에게 적합하지만 프론트 엔드 개발 리소스는 JavaScript만큼 풍부하지 않습니다. 2) Python은 데이터 과학 및 기계 학습 라이브러리에서 강력하며 JavaScript는 프론트 엔드 개발 라이브러리 및 프레임 워크에서 더 좋습니다. 3) 둘 다 풍부한 학습 리소스를 가지고 있지만 Python은 공식 문서로 시작하는 데 적합하지만 JavaScript는 MDNWebDocs에서 더 좋습니다. 선택은 프로젝트 요구와 개인적인 이익을 기반으로해야합니다.

C/C에서 JavaScript로 전환하려면 동적 타이핑, 쓰레기 수집 및 비동기 프로그래밍으로 적응해야합니다. 1) C/C는 수동 메모리 관리가 필요한 정적으로 입력 한 언어이며 JavaScript는 동적으로 입력하고 쓰레기 수집이 자동으로 처리됩니다. 2) C/C를 기계 코드로 컴파일 해야하는 반면 JavaScript는 해석 된 언어입니다. 3) JavaScript는 폐쇄, 프로토 타입 체인 및 약속과 같은 개념을 소개하여 유연성과 비동기 프로그래밍 기능을 향상시킵니다.

각각의 엔진의 구현 원리 및 최적화 전략이 다르기 때문에 JavaScript 엔진은 JavaScript 코드를 구문 분석하고 실행할 때 다른 영향을 미칩니다. 1. 어휘 분석 : 소스 코드를 어휘 단위로 변환합니다. 2. 문법 분석 : 추상 구문 트리를 생성합니다. 3. 최적화 및 컴파일 : JIT 컴파일러를 통해 기계 코드를 생성합니다. 4. 실행 : 기계 코드를 실행하십시오. V8 엔진은 즉각적인 컴파일 및 숨겨진 클래스를 통해 최적화하여 Spidermonkey는 유형 추론 시스템을 사용하여 동일한 코드에서 성능이 다른 성능을 제공합니다.

실제 세계에서 JavaScript의 응용 프로그램에는 서버 측 프로그래밍, 모바일 애플리케이션 개발 및 사물 인터넷 제어가 포함됩니다. 1. 서버 측 프로그래밍은 Node.js를 통해 실현되며 동시 요청 처리에 적합합니다. 2. 모바일 애플리케이션 개발은 재교육을 통해 수행되며 크로스 플랫폼 배포를 지원합니다. 3. Johnny-Five 라이브러리를 통한 IoT 장치 제어에 사용되며 하드웨어 상호 작용에 적합합니다.


핫 AI 도구

Undresser.AI Undress
사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover
사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool
무료로 이미지를 벗다

Clothoff.io
AI 옷 제거제

AI Hentai Generator
AI Hentai를 무료로 생성하십시오.

인기 기사

뜨거운 도구

SublimeText3 중국어 버전
중국어 버전, 사용하기 매우 쉽습니다.

MinGW - Windows용 미니멀리스트 GNU
이 프로젝트는 osdn.net/projects/mingw로 마이그레이션되는 중입니다. 계속해서 그곳에서 우리를 팔로우할 수 있습니다. MinGW: GCC(GNU Compiler Collection)의 기본 Windows 포트로, 기본 Windows 애플리케이션을 구축하기 위한 무료 배포 가능 가져오기 라이브러리 및 헤더 파일로 C99 기능을 지원하는 MSVC 런타임에 대한 확장이 포함되어 있습니다. 모든 MinGW 소프트웨어는 64비트 Windows 플랫폼에서 실행될 수 있습니다.

드림위버 CS6
시각적 웹 개발 도구

mPDF
mPDF는 UTF-8로 인코딩된 HTML에서 PDF 파일을 생성할 수 있는 PHP 라이브러리입니다. 원저자인 Ian Back은 자신의 웹 사이트에서 "즉시" PDF 파일을 출력하고 다양한 언어를 처리하기 위해 mPDF를 작성했습니다. HTML2FPDF와 같은 원본 스크립트보다 유니코드 글꼴을 사용할 때 속도가 느리고 더 큰 파일을 생성하지만 CSS 스타일 등을 지원하고 많은 개선 사항이 있습니다. RTL(아랍어, 히브리어), CJK(중국어, 일본어, 한국어)를 포함한 거의 모든 언어를 지원합니다. 중첩된 블록 수준 요소(예: P, DIV)를 지원합니다.

스튜디오 13.0.1 보내기
강력한 PHP 통합 개발 환경
