『javascript高級プログラム設計』学習ノート|10.14-10.16.クローズドパッケージ
14557 ワード
先端小讴に注目して、オリジナルの技術記事をもっと読みます.
関連コード→
閉パケットとは、通常、ネストされた関数で実装される別の関数の役割ドメイン内の変数を参照する関数です(関数が外部変数にアクセスしている場合、それは閉パケットです). 閉パケットにおける関数の役割ドメインチェーンには、外部関数変数への参照 がある.グローバルな役割ドメインで閉包関数にアクセスするために、通常、外部関数内で内部閉包関数 が戻る.
したがって、外部関数が閉パケットで参照するアクティブなオブジェクトは、外部関数の実行後に破棄されることはなく、メモリに残る である.メモリを解放するには、外部関数のアクティブオブジェクトへの閉パッケージ関数の参照 を解除する必要がある.
閉パッケージ内で グローバル関数で呼び出され、非厳格モードでは に等しい.は、あるオブジェクトのメソッドとして呼び出す、 を指す.匿名関数は、匿名関数を呼び出すオブジェクト を指すオブジェクトにバインドされない.
関数が呼び出されると、変数 特定の場合の
異なるゴミ回収メカニズムを使用するため、IE 9の前にパケットを閉じるIEブラウザでは、HTML要素がパケットを閉じる役割ドメインに保存されると、 が破棄されないという問題が発生する.
が直ちに呼び出す匿名関数は、関数宣言と同様に括弧に含まれる の即時呼び出し関数式(IIFE)とも呼ばれる. ES 5はブロックレベルの役割ドメインをサポートしていないが、IIFEシミュレーション を使用することができる. ES 6はブロックレベルの役割ドメインをサポートし、IIFEを必要とせずに同様の機能 を実現することができる.クリックハンドラを実行する場合、反復変数の値はループ終了時の最終値であり、表示する値 をクリックするたびにIIFEまたはブロックレベルの役割ドメインでロックすることができる.と同様に、タイムアウト論理を実行する場合、反復変数の値はループ終了をもたらす値であり、IIFEまたはブロックレベルの役割ドメインを使用して反復する値 をロックすることもできる.
関数またはブロックに定義変数は、プライベート(関数またはブロックの外部がアクセスできない変数) とみなすことができる.プライベート変数は、関数パラメータ、ローカル変数、および関数内部で定義された他の関数 を含む.特権メソッドは、関数のプライベート変数(およびプライベート関数)にアクセスできる共通のメソッドであり、構造関数において を実現することができる.同構造関数の欠点は、構造関数でプライベート変数を実現する問題は、各インスタンスがメソッド(プライベートメソッド&特権メソッド)を再作成し、メカニズムが同じFunctionオブジェクトが を複数回インスタンス化することである.
匿名関数式を使用してプライベート役割ドメインを作成し、特権メソッドを実装します. プライベート変数とプライベートメソッドの定義 プライベート変数は静的プライベート変数として共有するが、各インスタンスには存在しない .
コンストラクタの定義 関数式定義コンストラクション関数(関数宣言によって内部関数が作成される) キーワード定義コンストラクタを使用することなく、グローバル役割ドメインに を作成する.
共有メソッドの定義(特権メソッド) は、構造関数のプロトタイプ上で を定義する.
この方式では、プライベート変数とプライベートメソッドはインスタンスによって共有され、特権メソッドはプロトタイプに定義され、インスタンスによっても が共有される.インスタンスを作成してもメソッドは再作成されませんが、特権メソッドを呼び出して静的プライベート変数を変更すると、すべてのインスタンス に影響します.
は、単一のオブジェクトに基づいて拡張され、役割ドメインチェーンによってプライベート変数と特権メソッドを関連付けます. は、一例のオブジェクトのオブジェクト字面量を、即時呼び出しの関数式 に拡張する.匿名関数の内部で、プライベート変数とプライベートメソッド を定義する匿名関数の内部では、公開アクセス属性とメソッドのみを含むオブジェクトの字面量 が返される.
本質的には、このモードは、単一のオブジェクトの共通インタフェース をオブジェクトの字面量で定義する.
は、モジュールモードを使用して、オブジェクトを返す前に強化され、特定のタイプのインスタンスとして単一のオブジェクトに適していますが、追加のプロパティまたはメソッドを追加するシーンを追加する必要があります. 匿名関数の内部で、プライベート変数とプライベートメソッド を定義する匿名関数の内部で、ある(特定の)タイプのインスタンス を作成する.インスタンスオブジェクトに共有属性とメソッド(拡張) を追加はインスタンスオブジェクト を返す.
は、モジュールモードの単一のオブジェクト共通インタフェースを例にとる、 .
プライベート変数&プライベートメソッド
特権メソッド
欠点
コンストラクタ
インスタンスで独立
インスタンス
各インスタンスのメソッドの再作成(プライベートメソッド&特権メソッド)
プライベートドメイン
プライベート役割ドメインで、静的、共有
コンストラクタのプロトタイプ
特権メソッドを呼び出してプライベート変数を変更し、他のインスタンスに影響を与える
モジュールモード
プライベート役割ドメインで独立
単一オブジェクト上
モジュール拡張モード
プライベート役割ドメインで独立
インスタンスオブジェクト上
閉鎖とは何ですか?その役割は何ですか. 矢印関数を使用しない場合、thisはグローバルメソッドとローカルメソッドで呼び出されたとき、それぞれどこを指しますか?匿名関数のthisなら? 関数がネストされている場合、内部関数は外部関数のthisとargumentsにどのようにアクセスしますか? 今すぐ呼び出される関数式とは?ブロックレベルの役割ドメイン をコードでシミュレートしてください.コード実装機能:すべてのdiv要素を取得し、異なるdivをクリックして対応するインデックス値を表示してください.IIFEとブロックレベルの役割ドメインでそれぞれ を実現することが要求される.コード実装機能:1秒後に0~4のデジタル反復を実現してください.IIFEとブロックレベルの役割ドメインでそれぞれ を実現することが要求される.プライベート変数とは?どのような内容が含まれますか? 特権方法とは何ですか?コードを書いて、構造関数の中で特権の方法を実現して、そしてこの方法に何の問題があるかを話してください. コードを書いて、プライベート変数を通じて特権方法を実現して、この方法に何の限界があるかを話して証明してください. コードを書いてください.モジュールモードによって一例のオブジェクトの共通インタフェースを定義し、Webコンポーネント登録 を実現します.モジュール拡張モードはどんなシーンに適していますか?コードでそのモードのWebコンポーネント登録 を実現してください.
関連コード→
10.14閉パッケージ
したがって、
function arraySort(key, sort) {
return function (a, b) {
// , key sort,
let va = a[key]
let vb = b[key]
if (sort === 'asc' || sort === undefined || sort === '') {
// :va > vb
if (va > vb) return 1
else if (va < vb) return -1
else return 0
} else if (sort === 'desc') {
// :va < vb
if (va < vb) return 1
else if (va > vb) return -1
else return 0
}
}
}
let compareNames = arraySort('name') // , arraySort key sort ,
let result = compareNames({ name: 'Nicholas' }, { name: 'Matt' }) //
compareNames = null // arraySort ,
10.14.1 thisオブジェクト
this
を使用すると、コードがより複雑になります.内部関数が矢印関数を使用していない場合、this
は実行関数のコンテキストにバインドされます.this
がwindow
を指し、厳格モードはundefined
this
は、そのオブジェクトglobal.identity = 'The Window' // vscode node , window, window global
let object = {
identity: 'My Object',
getIdentityFunc() {
return function () {
return this.identity
}
},
}
console.log(object.getIdentityFunc()) // ƒ () { return this.identity },
console.log(object.getIdentityFunc()()) // 'The Window', this.identity,this
this
とthis
が自動的に作成され、内部関数は外部関数の2つの変数に直接アクセスできません.アクセスするには、閉パケットでアクセス可能な別の変数に参照を保存する必要があります.let object2 = {
identity: 'My Object',
getIdentityFunc() {
let that = this // this that
return function () {
return that.identity // ( ) that,that getIdentityFunc() this( this)
}
},
}
console.log(object2.getIdentityFunc()()) // 'My Object', that.identity,that getIdentityFunc this
arguments
値let object3 = {
identity: 'My Object',
getIdentity() {
return this.identity
},
}
console.log(object3.getIdentity()) // 'My Object'
console.log(object3.getIdentity) // [Function: getIdentity], getIdentity()
console.log((object3.getIdentity = object3.getIdentity)) // [Function: getIdentity], getIdentity() object3.getIdentity
console.log((object3.getIdentity = object3.getIdentity)()) // 'The Window', ,this
console.log((object3.funcA = object3.getIdentity)()) // 'The Window', getIdentity() ,
object3.funcB = object3.getIdentity
console.log(object3.funcB()) // 'My Object', object3 ,this object3
10.14.2メモリリーク
function assignHandler() {
let element = document.getElementById('someElement')
element.onclick = () => {
console.log(element.id) // element, element
}
}
function assignHandler2() {
let element = document.getElementById('someElement')
let id = element.id // element.id id
element.onclick = () => {
console.log(id) // element, element.id id
}
element = null // element ,
}
10.15今すぐ呼び出される関数式
;(function () {
//
})()
;(function () {
for (var i = 0; i < 3; i++) {
console.log(i) // 0、1、2
}
})()
console.log(i) // ReferenceError: i is not defined,i ( )
{
let i = 0
for (i = 0; i < 3; i++) {
console.log(i) // 0、1、2
}
}
console.log(i) // ReferenceError: i is not defined
for (let i = 0; i < 3; i++) {
console.log(i) // 0、1、2
}
console.log(i) // ReferenceError: i is not defined
let divs = document.querySelectorAll('div')
for (var i = 0; i < divs.length; ++i) {
divs[i].addEventListener(
'click',
// : ( )
// function(){
// console.log(i);
// }
// : ,
(function (_i) {
return function () {
console.log(_i)
}
})(i) //
)
}
for (let i = 0; i < divs.length; ++i) {
// let ,
divs[i].addEventListener('click', function () {
console.log(i)
})
}
for (var i = 0; i < 5; i++) {
// , 5
setTimeout(() => {
console.log(i) // 5、5、5、5、5
}, 0)
}
for (var i = 0; i < 5; i++) {
// , ,
;(function (_i) {
setTimeout(() => {
console.log(_i) // 0、1、2、3、4
}, 0)
})(i)
}
for (let i = 0; i < 5; i++) {
// let :
setTimeout(() => {
console.log(i) // 0、1、2、3、4
}, 0)
}
10.16プライベート変数
function add(num1, num2) {
// 3 : num1、 num2、 sum
let sum = num1 + num2
return sum
}
function MyObject() {
let privateVariable = 10
function privateFunction() {
console.log('privateFunction')
return false
}
// ( ): privateVariable privateFunction()
this.publicMethod = function () {
console.log('privateVariable', privateVariable++)
return privateFunction()
}
}
let obj = new MyObject()
obj.publicMethod()
/*
privateVariable 10
privateFunction
*/
function Person(name) {
/* name , getName() setName() */
this.getName = function () {
return name
}
this.setName = function (_name) {
name = _name
}
}
let person = new Person('Nicholas') // ( & )
console.log(person.getName()) // 'Nicholas'
person.setName('Greg')
console.log(person.getName()) // 'Greg'
10.16.1静的プライベート変数
;(function () {
/* , */
// ,
let privateVariable = 10
function privateFunction() {
return false
}
// : & ( )
MyObject = function () {}
// / ( ):
MyObject.prototype.publicMethod = function () {
console.log('privateVariable', privateVariable++)
return privateFunction()
}
})()
;(function () {
// name,
let name = ''
// ,
Person = function (_name) {
name = _name
}
// ,
Person.prototype.getName = function () {
return name
}
Person.prototype.setName = function (_name) {
name = _name
}
})()
let person1 = new Person('Nicholas')
console.log(person1.getName()) // 'Nicholas'
person1.setName('Matt')
console.log(person1.getName()) // 'Matt'
let person2 = new Person('Michael')
console.log(person2.getName()) // 'Michael',
console.log(person1.getName()) // 'Michael',
10.16.2モジュールモード
let singleton = (function () {
/* , */
// ,
let privateVariable = 10
function privateFunction() {
return false
}
//
return {
publicProperty: true,
publicMethod() {
console.log(++privateVariable)
return privateFunction
},
}
})()
console.log(singleton) // { publicProperty: true, publicMethod: [Function: publicMethod] }
singleton.publicMethod() // 11
function BaseComponent() {} // BaseComponent
let application = (function () {
let components = new Array() // components
components.push(new BaseComponent()) // , BaseComponent
/* */
return {
// getComponentCount() :
getComponentCount() {
return components.length
},
// registerComponent() :
registerComponent(component) {
if (typeof component === 'object') {
components.push(component)
}
},
// getRegistedComponents() :
getRegistedComponents() {
return components
},
}
})()
console.log(application.getComponentCount()) // 1
console.log(application.getRegistedComponents()) // [ BaseComponent {} ], BaseComponent
function APPComponent() {} // APPComponent
application.registerComponent(new APPComponent()) // APPComponent
console.log(application.getComponentCount()) // 2
console.log(application.getRegistedComponents()) // [ BaseComponent {}, APPComponent {} ], BaseComponent APPComponent
10.16.3モジュール強化モード
function CustomType() {} //
let singleton2 = (function () {
// ,
let privateVariable = 10
function privateFunction() {
return false
}
//
let object = new CustomType()
//
object.publicProperty = true
object.publicMethod = function () {
console.log(++privateVariable)
return privateFunction
}
//
return object
})()
console.log(singleton2) // CustomType { publicProperty: true, publicMethod: [Function: publicMethod] }
singleton2.publicMethod() // 11
this
がapplication
コンポーネントのインスタンスである必要がある場合、モジュール拡張モードを使用して作成することができる:let application2 = (function () {
let components = new Array() // components
components.push(new BaseComponent()) // , BaseComponent
let app = new BaseComponent() //
/* */
// getComponentCount() :
app.getComponentCount = function () {
return components.length
}
// registerComponent() :
app.registerComponent = function (component) {
if (typeof component === 'object') {
components.push(component)
}
}
// getRegistedComponents() :
app.getRegistedComponents = function () {
return components
}
return app //
})()
console.log(application2) // BaseComponent { getComponentCount: [Function (anonymous)], registerComponent: [Function (anonymous)], getRegistedComponents: [Function (anonymous)] }
console.log(application2.getComponentCount()) // 1
console.log(application2.getRegistedComponents()) // [ BaseComponent {} ], BaseComponent
application2.registerComponent(new APPComponent()) // APPComponent
console.log(application2.getComponentCount()) // 2
console.log(application2.getRegistedComponents()) // [ BaseComponent {}, APPComponent {} ], BaseComponent APPComponent
プライベート変数&プライベートメソッド
特権メソッド
欠点
コンストラクタ
インスタンスで独立
インスタンス
各インスタンスのメソッドの再作成(プライベートメソッド&特権メソッド)
プライベートドメイン
プライベート役割ドメインで、静的、共有
コンストラクタのプロトタイプ
特権メソッドを呼び出してプライベート変数を変更し、他のインスタンスに影響を与える
モジュールモード
プライベート役割ドメインで独立
単一オブジェクト上
モジュール拡張モード
プライベート役割ドメインで独立
インスタンスオブジェクト上