在这章节,我总结的有四点。函数分类、闭包、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 Window
2)、存在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()) // chujiu
2、对外暴露(属性方法也可称之为接口吧)
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() // 私有方法