2020-11-20

共有属性和私有属性指什么

function constructor() {1
  var clure_v = "a"; // 闭包属性
  var clure_f = function () {
    // 私有方法
    // code
    console.log(clure_v);
  };

  this.private_v = "b"; // 私有属性
  // 私有方法
  this.private_f = function () {
    console.log(this.clure_v,clure_v);
    clure_v += "a";
    clure_f();
  };
}
constructor.prototype.public_v = "c";
constructor.prototype.public_f = function () {
  console.log(this.clure_v, this.private_v, this.public_v);
};
console.log(constructor);
let c1 = new constructor();
console.log(c1);
console.log(c1.clure_v); //undefined
console.log(c1.private_v); //'b'
console.log(c1.public_v); //'c'
console.log(constructor.clure_v); //undefined
console.log(constructor.private_v); //undefined
console.log(constructor.public_v); //undefined
c1.private_f();
//undefined 'a'  'aa'
c1.private_f();
//undefined 'aa'  'aaa'
c1.public_f(); //undefined "b" "c"
console.log(c1.hasOwnProperty("clure_v")); //false
console.log(c1.hasOwnProperty("private_v")); //true
console.log(c1.hasOwnProperty("public_v")); //false
console.log("clure_v" in c1); //false
console.log("private_v" in c1); //true
console.log("public_v" in c1); //true

从上面的例子中我们可以得到

  1. JavaScript中的属性有内部定义不用this指向的属性,我们姑且称其为闭包属性,因为它对其属性起到一个保存和保护的作用,不会污染外部资源。in hasOwnProperty都不能检测到他,不能使用this访问,
  2. 另外有私有属性,就是在构造函数内部使用this指向定义的属性,该属性可以使用in hasOwnProperty检测来判断其是否是一个对象的属性
  3. 共有属性,及原型链上的属性,该属性可以通过this访问,可以使用in,检测出来,不能使用hasOwnProperty检测出来。

检测name是对象obj的属性

in 操作符

特点是无论是私有属性还是共有属性,只要有,就会返回true

hasOwnProperty

特点是,只有检测对象是其私有属性时才会返回true,否则返回false

JavaScript如何确定name是对象obj私有属性

obj.hasOwnProperty('name')

JavaScript如何确定name是对象obj共有属性

function getPubProperty(obj, attr) {
  /*
  第一种方法 使用 in 和 hasOwnProperty 
  已知,in可以用来判断共有和私有属性,hasOwnProperty可以用来判断私有属性,那么如果一个属性用in判断返回true,用hasOwnProperty判断返回false,就说明这个属性是共有属性
  但是,需要注意的是:如果一个属性既是共有属性又是私有属性,判断就会出错
  */
  /**
   * 第二种方法,也是最正确的方法
   * 就是检测原型上的属性,因为原型链上的属性都是共有的
   */
  let proto = obj.prototype;
  while (proto) {
    if (proto.hasOwnProperty(attr)) {
      return true;
    }
    proto = proto.prototype;
  }
  return false;
}

console.log(getPubProperty(c1, "public_v")); //true
console.log(getPubProperty(c1, "public_f")); //true
console.log(getPubProperty(c1, "private_v")); //false

对象遍历问题及解决方案

我们通常所用的遍历方式是 (for ... in ...for ... of ...)

for ... in ...

for ... in ...循环的特点是

  1. 对象的私有属性和共有属性都会被遍历到
  2. 但是不会遍历到对象的symbol属性
let sy = Symbol();
let obj = {
  2: 2,
  1: 1,
  a: "a",
  b: "a",
  [sy]: "Symbol(sy)",
};
obj.c = "c";
Object.prototype.publica = "publica";
obj.d = "d";
for (const key in obj) {
  console.log(key);
  // if (obj.hasOwnProperty(key)) {
  //   console.log(key);
  // }
  //在上面的控制下只会输出
}
/**
 * 1
 * 2
 * 'a'
 * 'b'
 * 'c'
 * 'd'
 * 'publica'
 */

for ... of ...

for ... of ...循环的特点是

其循环对象必须要有具有Symbol.iterator属性,调用这个接口就会返回一个遍历器对象。

原生部署了这个接口的数据结构如下

  1. Array
  2. Map
  3. Set
  4. String
  5. TypedArray
  6. 函数的arguments对象
  7. NodeList对象

故而我们在使用for ... of ...循环遍历对象的时候,需要使用中间件将对象转化为具有Symbol.iterator接口的对象,这些中间件可以是如下几个:

  1. Object.keys(obj)

    返回一个数组,遍历对象私有属性,但是不遍历Symbol属性和共有属性

    console.log(Object.keys(obj));//["1", "2", "a", "b", "c", "d"]
    
  2. Object.values(obj)

    返回一个数组,里面是对象私有属性(不含Symbol属性)的值

    console.log(Object.values(obj));[1, 2, "a", "a", "c", "d"]
    
  3. Object.entries()

    返回一个二维数组,里面是对象私有属性(不含Symbol属性)的[‘键’,‘值’]

    console.log(Object.entries(obj));
    /*
    0: (2) ["1", 1]
    1: (2) ["2", 2]
    2: (2) ["a", "a"]
    3: (2) ["b", "a"]
    4: (2) ["c", "c"]
    5: (2) ["d", "d"]
    */
    
  4. Object.getOwnPropertyNames(obj)

    返回一个数组

    ["1", "2", "a", "b", "c", "d"]
    

    Object.keys(obj)结果相同

  5. Object.getOwnPropertySymbols(obj)

    返回一个数组,遍历对象Symbol私有属性

    [Symbol()]
    
  6. Reflect.ownKeys(obj)

    返回一个数组,遍历对象的包含Symbol属性的私有属性

    ["1", "2", "a", "b", "c", "d", Symbol()]
    

上面这几种遍历器方法都会遵循以下几个规则

  1. 首先遍历所有属性名为数值的属性,按照数字排序
  2. 其次遍历所有属性名为字符串的属性,按照生成时间排序
  3. 最后遍历所有属性名为Symbol值的属性,按照生成时间排序
  4. 先遍历私有属性,再遍历共有属性
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值