> For the complete documentation index, see [llms.txt](https://gitbook.aiaod.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://gitbook.aiaod.com/programming/she-ji-mo-shi/bian-cheng-gai-nian.md).

# 编程概念

* closure 闭包：一个子函数，引用父函数的变量，当父函数执行完成，子函数依然能访问这些变量。
* argument drilling: 指的是在开发的时候，函数在调用链的时候，有很多参数要传递，比如A调用B，传了一些参数，B调用C的时候，又要传这个参数。有几个办法可以解决这个问题
  * 对象传参：将相关参数封装到一个对象里
  * 依赖注入：用依赖注入来管理和传递函数所需要的依赖项
  * 使用全局变量虽然也能解决，但可能会引入其他问题，比如命名冲突，可维护性差，难以测试等，不推荐使用。
  * 使用 closure 闭包在一定程度上也能解决参数的问题，一个示例如下
    * 比如一个计算折扣的程序，原始写法如下

```javascript
async function getUserDiscounts() {
    return {
        P001: 5,
        P002: 10
    }
}

async function getCategoryDiscounts() {
    return {
        electronics: 15,
        clothing: 5
    }
}

function proceeProducts(products, userDiscounts, categoryDiscounts) {
    return products
    .map((product) => {
        const userDiscount = userDiscounts[product.id] || 0;
        const categoryDiscount = categoryDiscounts[product.category] || 0;
        const totalDiscount = userDiscount + categoryDiscount;
        const finalPrice = product.price - product.price * (totalDiscount / 100);
        return {
            ...product, 
            finalPrice: finalPrice.toFixed(2)
        };
    })
    .filter((product) => product.finalPrice <= 80)
    .map((product) => product.id)
}

async function main() {
    const products = [
        {id: "P001", category: "electronics", price: 100},
        {id: "P002", category: "clothing", price: 50},
        {id: "P003", category: "electronics", price: 100},
        {id: "P004", category: "clothing", price: 80}
    ]
    const userDiscounts = await getUserDiscounts();
    const categoryDiscounts = await getCategoryDiscounts();

    const processedProducts = proceeProducts(
        products,
        userDiscounts,
        categoryDiscounts
    );

    console.log(
        processedProducts.reduce(
            (obj, key) => {obj[key] = key; return obj;}, {}
        )
    );
}

main()
```

此时折扣的逻辑在多个地方都会用到，此时我们可以创建一个createDiscountCalculator的函数专门计算折扣，这个函数需要接收 userDiscounts 和 categoryDiscounts 作为输入，在专门处理某一个商品时，然后再通过这个 discountCalculator 查一下商品折扣，具体改法是：

```javascript
async function getUserDiscounts() {
    return {
        P001: 5,
        P002: 10
    }
}

async function getCategoryDiscounts() {
    return {
        electronics: 15,
        clothing: 5
    }
}

function createDiscountCalculator(userDiscounts, categoryDiscounts) {
    return function (product){
    const userDiscount = userDiscounts[product.id] || 0;
    const categoryDiscount = categoryDiscounts[product.category] || 0;
    const totalDiscount = userDiscount + categoryDiscount;
    const finalPrice = product.price - product.price * (totalDiscount / 100);

    return  finalPrice.toFixed(2);
    } 
}

function proceeProducts(products, discountCalculator) {
    return products
    .map((product) => {
        const finalPrice = discountCalculator(product);
        return {
            ...product, 
            finalPrice: finalPrice
        };
    })
    .filter((product) => product.finalPrice <= 80)
    .map((product) => product.id)
}

async function main() {
    const products = [
        {id: "P001", category: "electronics", price: 100},
        {id: "P002", category: "clothing", price: 50},
        {id: "P003", category: "electronics", price: 100},
        {id: "P004", category: "clothing", price: 80}
    ]
    const userDiscounts = await getUserDiscounts();
    const categoryDiscounts = await getCategoryDiscounts();
    const discountCalculator = createDiscountCalculator(
        userDiscounts,
        categoryDiscounts
    );

    const processedProducts = proceeProducts(
        products,
        discountCalculator
    );

    console.log(
        processedProducts
    );

    console.log(
        processedProducts.reduce(
            (obj, key) => {obj[key] = key; return obj;}, {}
        )
    );
}

main()
```

下面是一个python 通过闭包的一个实现

```python
from decimal import Decimal, getcontext  
def user_discount():  
    return {  
        "P001": 5,  
        "P002": 10  
    }  
  
  
def category_discount():  
    return {  
        "electronics": 15,  
        "clothing": 5  
    }  
  
  
def discount_calculator(user_discount, category_discount):  
    def discount(product):  
        user_discount_percentage = user_discount.get(product["id"], 0)  
        category_discount_percentage = category_discount.get(product["category"], 0)  
        discount_percentage = user_discount_percentage + category_discount_percentage  
        discount_amount = product["price"] * Decimal(discount_percentage / 100)  
        discounted_price = product["price"] - discount_amount  
        return discounted_price  
    return discount  
  
  
def proceed_products(products, discount_calculator):  
    discounted_product = [{**product, 'finalPrice': discount_calculator(product)} for product in products]  
  
    filtered_products = [  
        product["id"] for product in discounted_product if product['finalPrice'] < 80  
    ]  
    return filtered_products  
  
if __name__ == '__main__':  
    products = [  
        {  
            "id": "P001",  
            "category": "electronics",  
            "price": 100  
        },  
        {  
            "id": "P002",  
            "category": "clothing",  
            "price": 50  
        },  
        {  
            "id": "P003",  
            "category": "electronics",  
            "price": 100  
        },  
        {  
            "id": "P004",  
            "category": "clothing",  
            "price": 80  
        }  
    ]  
    user_discount = user_discount()  
    category_discount = category_discount()  
    discount_calculator = discount_calculator(user_discount, category_discount)  
    discount_products = proceed_products(products, discount_calculator)  
    print(discount_products)
```
