在这章节,我总结的有四点。函数分类、闭包、this指向和私有变量和函数。
一、函数分类 关于函数,我们可以通过new字符创建,同时也可以通过字面量创建。但是所创建的各个函数有什么区分呢?又有什么分类呢?
1、按照名称分类(注意:只针对函数本身而言) 1.1、非匿名函数 1.2、匿名函数
// 非匿名函数 function nonAnonymous() { console.log('我是非匿名函数') } // 匿名函数 const anonymous = function() { console.log('我是匿名函数') }2、按照执行情况分类 2.1、非自执行函数 2.2、自执行函数
// 非自执行函数 function nonSelfexec() { console.log('我是非自执行函数') }; // 自执行函数 (function() { console.log('我是自执行函数种类一') }()); //这个分号是必加的,否则报错!js会自动的认为你是匿名函数自调 (function selfexec() { console.log('我是自执行函数种类二') }());3、在非自执行函数中按照执行方式分类 3.1、非回调函数(显式执行)自己手动定义,自己手动 3.2、回调函数(非显式执行)自己手动定义,事件驱动执行
// 显式调用函数 function nonCallBack() { console.log('我是显式调用函数') }; nonCallBack(); // 回调函数 const arr = [1, 2, 3] const callBack = function(item) { console.log('我是回调用函数') return item < 3 } arr.filter(callBack)二、闭包 简单来说就是通过return一个函数体,将原先函数内部数据带离到外部,使得原先函数作用域即使被销毁,但是原型链上的变量对象也无法被释放。其缺点会造成内存的泄露。
const test = function() { var count = 0 return function() { count++ return count } } const count = test() console.log(count()) // 1 console.log(count()) // 2 console.log(count()) // 3注意:所有被return的的函数,所携带调用的数据源只有一个,那就是原函数内部定义的局部变量。因此任何一个return函数对数据的改变都会影响其他return函数内部数据值。
三、this指向 this直白点就是当前执行代码的环境对象,然而具体怎么确定this值,就要看执行环境。
1、在函数及类中的this 1.1、构造函数中:new functionName()返回的是实例对象,也就是其内部的this。而food是指向实例对象的一个地址。就好比:const obj = { code... }
function Food() { this.category = 'food' console.log('thisFood', this) // thisFood Food {category: "food"} } const food = new Food()1.2、class类中:new className()返回的是实例对象,也就是其内部的this。而a是指向实例对象的一个地址。就好比:const obj = { code... }
class A{ coonstructor() { this.data = 'data' console.log('classA', this) } test() { console.log('classA', this) // classA A } } const a = new A() a.test()1.3、普通函数 注意:functionName只是一个指向函数体的地址,当我们没有对这个函数做任何的this绑定。在非严格模式中,默认this绑定Window,也就是functionName()等同于Window.functionName()。在严格模式中,禁止this绑定全局,也就是functionName()【执行】时,内部this为undfined。 1)、直接使用,没有this绑定动作
const fun = function() { console.log('funThis', this) } fun() // funThis Window function Food(name, price) { this.category = 'food' fun() } const food = new Food() // funThis Window class A{ coonstructor() { this.data = 'data' console.log('classA', this) } test() { fun() } } const a = new A() a.test() // funThis Window2)、存在this绑定动作
const fun = function() { console.log('funThis', this) } function Food(name, price) { this.category = 'food' this.fun = fun } const food = new Food() food.fun() // funThis Food {category: "food", fun: ƒ} class A{ constructor() { this.data = 'data' this.fun = fun } } const a = new A() a.fun() // funThis A {data: "data", fun: ƒ}2、this绑定方式 2.1、’='操作符 '='操作符的this绑定一般适用于在构造函数,类calss中或对象object外操作。比如:this.funName = funName或objName.attrName = funName,将指向函数体的地址拷贝赋值给实例对象中的一个属性值,从而当我们利用这个属性值调用函数体时,其内部this为实例对象。
const fun = function() { console.log('funThis', this) } const obj = {} obj.fun = fun obj.fun() // funThis {fun: ƒ} function Food(name, price) { this.category = 'food' this.fun = fun } const food = new Food() food.fun() // funThis Food {category: "food", fun: ƒ} class A{ constructor() { this.data = 'data' this.fun = fun } } const a = new A() a.fun() // funThis A {data: "data", fun: ƒ}2.2、’:'操作符 ':'操作符的this绑定一般适用于在对象object中操作。比如:attrName: funName,将指向函数体的地址拷贝赋值给对象中的一个属性值,从而当我们利用这个属性值调用函数体时,其内部this为实例对象。
const fun = function() { console.log('funThis', this) } const obj = { fun: fun } obj.fun() // funThis {fun: ƒ}2.3、apply/call/bind api文档
2.4、new字符隐式绑定 当我们使用new字符利用构造函数或则类calss时,会创建一个实例对象,并且将其内部this与所创建对象隐式绑定。返回值为实例对象。
function Food() { this.category = 'food' console.log('foodThis', this) } new Food() // foodThis Food {category: "food"} class A{ constructor() { this.data = 'data' console.log('aThis', this) } } new A() // aThis A {data: "data"}四、私有变量及函数 私有变量有两种方法,一种利用get/set从而使得可以不需要写明属性,已达到私有化目的;另一种则是利用对外暴露一个属性方法,从而操控私有变量和私有方法。
1、利用get/set
function Person(name) { this.get = function() { return name } this.set = function(value) { name = value } } const person = new Person('埋埋') console.log(person.get()) // 埋埋 person.set('chujiu') console.log(person.get()) // chujiu2、对外暴露(属性方法也可称之为接口吧)
function Person() { let privateVarible = '私有属性' function privateFun() { console.log('私有方法') } this.publicMehod = function () { console.log(privateVarible) return privateFun } } const person = new Person() const privateFun = person.publicMehod() // 私有属性 privateFun() // 私有方法