defineProperty

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>属性的操作</title>
</head>
<body>
    <script type="text/javascript">

        //bind 兼容
        if(!Function.prototype.bind){
            Function.prototype.bind = function(scope){
                var _this = this;
                return function(){
                    _this.call(scope);
                }
            }
        }
        /**
         * getter: 获取某一个对象的某个属性之前会回调的这个属性的getter的钩子函数
         * setter: 设置某一个对象的某个属性之前会回调的这个属性的setter的钩子函数
         *
         *一个对象的任意属性在没有设置setter和getter钩子函数的时候,默认系统有实现
         */
        var model = {
            name: "star",
            message: "this is message",
            isShow: true
        };
        //
        function observerFactory(model){
            for (var property in model ){
                addOSer(model, property, model[property]);
            }
        }
        function addOSer(model, property, value){
            Object.defineProperty(model, property,{
//            value:"star",
//            writable:false,//是否可写入
                enumerable: true,//是否可meiju
                configurable: false,//是否以后还可以配置name属性
                set:function(nvalue){
                    console.log("进入set设置");
                    this.value = nvalue;
                },
                get:function(){
                    console.log("进入get设置");
                    return this.value;
                }
            });
        }
        observerFactory(model);
        model.name = "xxx";

//        function observerFactory(model){
//            for (var property in model){
//                model.__defineSetter__(property, function(value){
//                    /**
//                     * 问题:property循环出来的一直是isShow,
//                     * 原因:闭包问题, observerFactory(model);执行了3次,所以property输出来的一直是isShow
//                     * 解决办法:用ES6语法,把var改成let(let指的是:只在当前的作用域有用)
//                     */
//                    console.log("已经进入了"+ property +"属性的setter");
//                    this.value = value;
//                });
//                model.__defineGetter__(property, function(){
//                    console.log("已经进入了"+ property +"属性的getter");
//                    return this.value;
//                });
//            }
//        }
//        observerFactory(model);
        /**
         * 我们可以在对象的原型链上找到这些方法,有些方法不是不存在,而是我们不关心它,
         * __defineGetter__(定义Getter):只要看到下划线开头的属性或者函数,代表是隐私的意思,不想让外面访问或者更改
         * __defineGetter__基于原型链的,所以每个对象都有__defineGetter__方法
         *
         * Object.defineGetter(); 静态方法 static model,准许我们使用的
         * __defineGetter__(私有的,可以调用)和Object.defineGetter()区别:
         * __defineGetter__私有的,可以调用,但是javascript引擎想告诉我们最好不要这个用,强行用也是可以的,
         * javascript提供了Object.defineGetter方法,这个方法和__defineGetter__一样,推荐使用Object.defineGetter方法
         */
//         model.__defineSetter__("message", function(value){
//             console.log("已经进入了message属性的setter");
//             this.value = value;
//         });
//         model.__defineGetter__("message", function(){
//             console.log("已经进入了message属性的getter");
//             /**
//              * (强行使用__defineGetter__):这里的this指的model本身,
//              */
//             return this.value;
//         });
        /**
         * 返回“undefined
         * 原因:当我们访问message属性的时候,__defineGetter__的钩子函数拦截了
         * 当我们访问message的时候,会先调用get message钩子函数,this.value是undefined,
         * 所以返回的是undefined
         *
         *解决办法:需要先设置在获取,先setter再getter
         */
//        model.name = "stas";
        console.log(model.name);
    </script>
</body>
</html>

  

原文地址:https://www.cnblogs.com/patriot/p/7612583.html