js用defineProperty深层监听对象时为什么我这样写没法调用到set?

function defineReactive(data,key,val){
    observe(val)
    let test = ''   //关键是这里,如果设成let test = val就没问题了,但不知道为什么
    let description = {
        enumerable:true,
        configurable:true,
        set:function(newVal){
            test = newVal   //或者这里不用test,直接用val = newVal也可以,但也不知道为什么
            console.log('属性' + key + '已经被监听了,现在值为:“' + newVal.toString() + '”')
        },
        get:function(){
            return test
        }
    }
    Object.defineProperty(data,key,description)
}

function observe(data){
    if(!data || typeof data !== 'object'){
        return
    }
    Object.keys(data).forEach(function(key){
        defineReactive(data,key,data[key])
    })
}
var library = {
    book1: {
        name: ''
    },
    book2: ''
};
observe(library);

library.book1.name = 'vue权威指南'  //没有执行set函数
library.book2 = '没有此书籍';   //这里却执行了set函数

遇到的问题在注释上面,求解答,感谢~