彩世界开奖app官网-彩世界平台官方网址(彩票平台)
做最好的网站
来自 前端技术 2019-11-28 11:59 的文章
当前位置: 彩世界开奖app官网 > 前端技术 > 正文

ES6之主要知识点(七)对象彩世界平台官方网址

2.new
function foo(){}
foo.prototype.z = 3;
var obj = new foo();
obj.y = 2;
obj.x = 1;

obj.x; //1
obj.y; //2
obj.z; //3
type of obj.toString; // 'function'
'z' in obj; //true,z从foo.prototype继承而来
obj.hasOwnProperty('z'); //false,obj这个对象本身没有z属性 

彩世界平台官方网址 1

function foo(){}
foo.prototype.z = 3;
var obj = new foo();
obj.y = 2;
obj.x = 1;
obj.z = 5;

obj.hasOwnProperty('z');//true
foo.prototype.z; //still 3
obj.z;  //5

obj.z = undefined;
obj.z;  //undefined
//此时如果要访问原型z,需要删除obj的z属性
delete obj.z; //true
obj.z; //3

delete obj.z; //再次删除,不会删除原型链
obj.z; //still 3!!!

注意点

Object.assign方法实行的是浅拷贝,而不是深拷贝。也就是说,如果源对象某个属性的值是对象,那么目标对象拷贝得到的是这个对象的引用

3.create

创建一个对象,对象的原型指向里面的参数

var obj = Object.create({x:1});
obj.x; //1
typeof obj.toString //'function'
obj.hasOwnProperty('x');//false

var obj = Object.create(null);
obj.toString //undefined

由于已经删除的属性的引用依然存在,所以这种不严谨的代码会造成内存泄漏,所以在销毁的属性是对象类型的时候,要遍历属性中的属性,依次删除。

可枚举性

对象的每个属性都有一个描述对象(Descriptor),用来控制该属性的行为。Object.getOwnPropertyDescriptor方法可以获取该属性的描述对象。

let obj = { foo: 123 };
Object.getOwnPropertyDescriptor(obj, 'foo')
//  {
//    value: 123,
//    writable: true,
//    enumerable: true,
//    configurable: true
//  }

描述对象的enumerable属性,称为”可枚举性“,如果该属性为false,就表示某些操作会忽略当前属性。

目前,有四个操作会忽略enumerablefalse的属性。

  • for...in循环:只遍历对象自身的和继承的可枚举的属性。
  • Object.keys():返回对象自身的所有可枚举的属性的键名。
  • JSON.stringify():只串行化对象自身的可枚举的属性。
  • Object.assign(): 忽略enumerablefalse的属性,只拷贝对象自身的可枚举的属性。
删除
var person = {age:20, title:'fe'};
delete person.age; //true
delete person['title'];//true
person.age;//undefined
//再次删除不存在的属性
delete person.age; //true,还是会返回true

delete Object.prototype;//false
//因为Object.prototype被配置为不可修改;
var descriptor = Object.getOwnPropertyDescriptor(Object,'prototype');
descriptor.configurable;//false
var o={"name":"zhang"};
"name" in o;//true;
“toString" in o;//true;

常见用途 

(1)为对象添加属性

class Point {
  constructor(x, y) {
    Object.assign(this, {x, y});
  }
}

(2)克隆对象

function clone(origin) {
  let originProto = Object.getPrototypeOf(origin);
  return Object.assign(Object.create(originProto), origin);
}

**(3)为属性指定默认值**

const DEFAULTS = {
  logLevel: 0,
  outputFormat: 'html'
};

function processContent(options) {
  options = Object.assign({}, DEFAULTS, options);
  console.log(options);
  // ...
}

注意,由于存在浅拷贝的问题,DEFAULTS对象和options对象的所有属性的值,最好都是简单类型,不要指向另一个对象。 

检测
var cat = new Object;
cat.legs = 4;
cat.name = 'Kitty';

'legs' in cat;//true
'abc' in cat;//false
'toString' in cat;//true,运算符in会向上查找,toString继承于Object.property
//检测属性是否为自身拥有
cat.hasOwnProperty('legs');//true
cat.hasOwnProperty('toString');//false
//检测属性是否可枚举
cat.propertyIsEnumberable('legs');//true
cat.propertyIsEnumberable('toSgring');//false

Object.create(prototype[,propertiesObject]);
参数
prototype:Object类型;作为新创建对象的原型对象;可以取值为null;
propertiesObject:为新创建对象绑定的属性;
返回值
返回指定原型对象上添加新属性后的对象。

3.Object.assign() 

Object.assign方法用于对象的合并,将源对象(source)的所有可枚举属性,复制到目标对象(target)。

Object.assign(target, source1, source2);

Object.assign方法的第一个参数是目标对象,后面的参数都是源对象。

注意,如果目标对象与源对象有同名属性,或多个源对象有同名属性,则后面的属性会覆盖前面的属性。

如果该参数不是对象,则会先转成对象,然后返回。

typeof Object.assign(2) // "object"

let obj = {a: 1};
Object.assign(obj, undefined) === obj // true
Object.assign(obj, null) === obj // true

Object.assign拷贝的属性是有限制的,只拷贝源对象的自身属性(不拷贝继承属性),也不拷贝不可枚举的属性(enumerable: false

遍历属性
//如果不想遍历原型链的属性
for(key in obj){
    if(obj.hasOwnProperty(key)){
    //do something
    }
}
var o={"name":"zhang"};
o.hasOwnProperty("name");//true;
o.hasOwnPropery("toString");//false;

7.Object.keys(),Object.values(),Object.entries()

let {keys, values, entries} = Object;
let obj = { a: 1, b: 2, c: 3 };

for (let key of keys(obj)) {
  console.log(key); // 'a', 'b', 'c'
}

for (let value of values(obj)) {
  console.log(value); // 1, 2, 3
}

for (let [key, value] of entries(obj)) {
  console.log([key, value]); // ['a', 1], ['b', 2], ['c', 3]
}

Object.values只返回对象自身的可遍历属性

Object.entries的基本用途是遍历对象的属性。

Object.entries方法的另一个用处是,将对象转为真正的Map结构。

var obj = { foo: 'bar', baz: 42 };
var map = new Map(Object.entries(obj));
map // Map { foo: "bar", baz: 42 }
读写
var yz;
if(obj.y){ //检测属性
    yz = obj.y.z
}
//利用运算符达到同样效果
var yz = obj && obj.y && obj.y.z

对象的扩展属性用以表示是否可以给对象添加新属性,内置对象和自定义对象都是默认可扩展的。宿主对象的可扩展性由javaScript引擎定义。

5.Object.getOwnPropertyDescriptors()

前面说过,Object.getOwnPropertyDescriptor方法会返回某个对象属性的描述对象(descriptor)。

ES2017 引入了Object.getOwnPropertyDescriptors方法,返回指定对象所有自身属性(非继承属性)的描述对象。

const obj = {
  foo: 123,
  get bar() { return 'abc' }
};

Object.getOwnPropertyDescriptors(obj)
// { foo:
//    { value: 123,
//      writable: true,
//      enumerable: true,
//      configurable: true },
//   bar:
//    { get: [Function: bar],
//      set: undefined,
//      enumerable: true,
//      configurable: true } }

该方法的引入目的,主要是为了解决Object.assign()无法正确拷贝get属性和set属性的问题。

Object.getOwnPropertyDescriptors方法的一个用处,是配合Object.create方法,将对象属性克隆到一个新对象。这属于浅拷贝

const clone = Object.create(Object.getPrototypeOf(obj),
  Object.getOwnPropertyDescriptors(obj));

自定义属性
Object.defineProperty(cat,'price',{enumerable:false,value:1000});
cat.propertyIsEnumberable('price');//false
cat.hasOwnProperty('price');//true

补充:属性一旦设置configurable:false,将不可再变回可配置

密封对象(seal)
Object.seal();
Object.isSealed();
这个方法除了能够将对象设置为不可扩展的,还可以将对象的所有自有属性都设置为不可配置的。

属性的遍历

ES6 一共有5种方法可以遍历对象的属性。

(1)for...in

for...in循环遍历对象自身的和继承的可枚举属性(不含 Symbol 属性)。

var a ={'b':232,'cc':'dd'}
for(let temp in a){
    console.log(temp)
}
//2 b
//2 cc

(2)Object.keys(obj)

Object.keys返回一个数组,包括对象自身的(不含继承的)所有可枚举属性(不含 Symbol 属性)。

(3)Object.getOwnPropertyNames(obj)

Object.getOwnPropertyNames返回一个数组,包含对象自身的所有属性(不含 Symbol 属性,但是包括不可枚举属性)。

(4)Object.getOwnPropertySymbols(obj)

Object.getOwnPropertySymbols返回一个数组,包含对象自身的所有 Symbol 属性。

(5)Reflect.ownKeys(obj)

Reflect.ownKeys返回一个数组,包含对象自身的所有属性,不管属性名是 Symbol 或字符串,也不管是否可枚举。

属性操作

var o={};
Object.defineProperty(o,"age",{value:26,writable:true,enumerable:true,configurable:true});
Object.freeze(o);
console.info(Object.isFrozen(o));//true;
console.info(Object.getOwnPropertyDescriptor(o,"age")["configurable"]);//false;
console.info(Object.getOwnPropertyDescriptor(o,"age")["writable"]);//false;
var p=Object.getPrototypeOf(o);//获取o的原型对象
p["name"]="zhang";
console.info(o.name);//"zhang";

2.Object.is() 

ES6 提出“Same-value equality”(同值相等)算法。Object.is就是部署这个算法的新方法。它用来比较两个值是否严格相等,

与严格比较运算符(===)的行为基本一致。

Object.is('foo', 'foo')
// true
Object.is({}, {})
// false
 0 === -0 //true
NaN === NaN // false

Object.is( 0, -0) // false
Object.is(NaN, NaN) // true
1.字面量
var obj = {x:1,y:2};
var obj2 = {
    x:1,
    y:2,
    o:{
        z:3,
        n:4
    }
};

检测属性
检测某个属性是否属于指定对象;可以使用in运算符或Object.prototype.hasOwnProperty()和Object.prototype.propertyIsEnumerable();
分以下几种情况:
1.检测的属性不区别是自有的还是继承过来的;

8.Null 传导运算符 

编程实务中,如果读取对象内部的某个属性,往往需要判断一下该对象是否存在。

比如,要读取message.body.user.firstName,安全的写法是写成下面这样。

const firstName = (message
  && message.body
  && message.body.user
  && message.body.user.firstName) || 'default';

这样的层层判断非常麻烦,因此现在有一个提案,引入了“Null 传导运算符”(null propagation operator)?.,简化上面的写法。

const firstName = message?.body?.user?.firstName || 'default';

“Null 传导运算符”有四种用法。

  • obj?.prop // 读取对象属性
  • obj?.[expr] // 同上
  • func?.(...args) // 函数或对象方法的调用
  • new C?.(...args) // 构造函数的调用 

创建对象

2.检测自有属性

4.属性的可枚举性和遍历

//不能删除继承属性
var p={x:1};
var o=Object.create(p);
console.info(o.x);//1
delete o.x;//true;
console.info(o.x);//1
//不能删除configurable为false的属性
var p=Object.create(Object.prototype,{
  name:{
      value:"zhang",
      writable:true,
      enumerable:true,
      configurable:false;
 }
});
delete p.name;//false;
//在全局作用域中通过var,function创建的变量和函数声明是不可配置的,不能删除
var x=1;
function test(){};
delete this.x;//false;
delete this.test;//false;
//严格模式和非严格模式使用delete
"use strict"
var p={x:1};
delete x;//报错
delete p.x;//true;
//delete后不是一个属性访问表达式
delete 1;//true

9.Object.defineProperty()

语法:

Object.defineProperty(obj, prop, descriptor)

参数说明:

obj:必需。目标对象 
prop:必需。需定义或修改的属性的名字
descriptor:必需。目标属性所拥有的特性

Object.defineProperty(obj,"newKey",{
    configurable:true | false,
    enumerable:true | false,
    value:任意类型的值,
    writable:true | false,
    get:function (){
        //当获取值的时候触发的函数
        return initValue;    
    },
    set:function (value){
        //当设置值的时候触发的函数,设置的新值通过参数value拿到
        initValue = value;
    }
});

 

var a=[];
var r=Object.prototype.toString.call(a);
console.info(r);//"[object,Array]";
r.slice(8,-1);//"Array";

6.__proto__属性,Object.setPrototypeOf(),Object.getPrototypeOf()

__proto__属性(前后各两个下划线),用来读取或设置当前对象的prototype对象。目前,所有浏览器(包括 IE11)都部署了这个属性。

Object.setPrototypeOf方法的作用与__proto__相同,用来设置一个对象的prototype对象,返回参数对象本身。它是 ES6 正式推荐的设置原型对象的方法。

let proto = {};
let obj = { x: 10 };
Object.setPrototypeOf(obj, proto);

proto.y = 20;
proto.z = 40;

obj.x // 10
obj.y // 20
obj.z // 40
var o={x:2};
for(item in o){
//打印自有属性x,因为继承的内置对象属性都是不可枚举的
console.info(item);//x;
}

1.属性的简洁表示法

ES6 允许直接写入变量和函数,作为对象的属性和方法。这样的书写更加简洁。

function f(x, y) {
  return {x, y};
}

// 等同于

function f(x, y) {
  return {x: x, y: y};
}

f(1, 2) // Object {x: 1, y: 2}

var o = {
  method() {
    return "Hello!";
  }
};

// 等同于

var o = {
  method: function() {
    return "Hello!";
  }
};

module.exports = { getItem, setItem, clear };
// 等同于
module.exports = {
  getItem: getItem,
  setItem: setItem,
  clear: clear
};

设置对象为不可扩展的
Object.preventExtensions()
这个方法只影响对象本身的可扩展性。如果给一个不可扩展对象的原型对象添加一个属性,对象仍然可以继承这个属性。

Object.getPrototypeOf() 

function Rectangle() {
  // ...
}

var rec = new Rectangle();

Object.getPrototypeOf(rec) === Rectangle.prototype
// true

Object.setPrototypeOf(rec, Object.prototype);
Object.getPrototypeOf(rec) === Rectangle.prototype
// false

创建对象
有三种方式可以创建对象
1.对象字面量
2.通过new关键词来创建对象
3.通过Object.create()方法来创建对象


2.枚举自有属性(enumerable为True)

var o={};
Object.preventExtensions(o);
console.info(Object.isExtensible(o));//false;
var p=Object.getPrototypeOf(o);//获取o的原型对象
p["name"]="zhang";
console.info(o.name);//"zhang";
var o={};
Object.defineProperty(o,"age",{value:26,writable:true,enumerable:true,configurable:true});
Object.seal(o);
console.info(Object.isSealed(o));//true;
console.info(Object.getOwnPropertyDescriptor(o,"age")["configurable"]);//false;
var p=Object.getPrototypeOf(o);//获取o的原型对象
p["name"]="zhang";
console.info(o.name);//"zhang";

判断对象是否是可扩展的
Object.isExtensible();

javaScript中的对象有内置对象宿主对象自定义对象
内置对象:数组,函数,日期,正则表达式;
宿主对象:javascript解析器所在的宿主,比如web浏览器,宿主环境定义的对象document,DOM对象等;
自定义对象:在js中自己创建的对象;

function deleteProperty(o, p) {

    function isObjectOfProperty(property) {
        return (Object.prototype.toString.call(o[property]) === "[object Object]") ? true : false;
    }

    if (arguments.length == 1 && typeof arguments[0] == "object") {
        for (var item in o) {
            isObjectOfProperty(item) ? deleteProperty(o[item]) : (delete o[item]);
        }
    } else if (arguments.length == 2 && typeof arguments[0] == "object" && typeof arguments[1] == "string") {
        isObjectOfProperty(p) ? deleteProperty(o[p]) : (delete o[p]);
    } else {
        return false;
    }
};
var o={p:{x:1}};
var n=o.p;
delete o.p;
console.info(n.x)//1;
var o={};
Object.defineProperty(o,"name",{value:"zhang",enumerable:false});
o.age=26;
o.propertyIsEnumerable("name");//false;
o.propertyIsEnumerable("age");//true;
var o={x:2};
Object.defineProperty(o,"y",{value:3});
Object.getOwnPropertyNames(o);// ["x", "y"]

查询属性
可以通过(.)运算符或([])方括号来获取属性的值。对于点运算符来说,右侧必须是一个以属性名称命名的简单标识符。对于方括号来说,方括号内必须是一个计算结果为字符串或可以转换为字符串的表达式,这个字符串就是属性的名字。ES3中,点运算符后面的标识符不能是保留字,只能通过方括号来访问它们,ES5对此放宽了限制,可以在点运算符后面直接使用保留字。
方括号的形式可以动态的访问属性,或者属性名中有空格出现的情况,推荐使用。

对象的原型属性是实例对象创建之初就设置好的,查询原型特性可以使用Object.getPrototypeOf();在ES3中没有与之对应的方法,通常使用表达式o.constructor.prototype来检测一个对象的原型(这种方式存在问题);要检测一个对象是否是另一个对象的原型,使用isPrototypeOf();

注意细节
1、delete只能删除自有属性,不能删除继承过来的属性;
2、delete不能删除可配置性为false的属性,可以删除不可扩展对象的可配置属性,比如prototype对象的可配置属性constructor;
3、通过变量声明和函数声明创建的全局对象的属性是不可配置的,不能用delete操作符删除;
4、在非严格模式中,删除全局对象的可配置属性时,可以省略对全局对象的引用,直接在delete操作符后跟随要删除的属性;在严格模式下则会报错;
5.delete操作符在什么情况下返回true/false;(删除不存在的属性,删除继承过来的属性,删除configuable为true的属性;这几种情况返回true)

存取器属性的setter和getter


数据属性有四个特性:
1.value(值属性);
2.writable(可写属性);------表明是否可以设置该属性的值(控制value这个属性);
3.enumerable(可枚举属性);------表明该属性是否可以通过for...in循环返回该属性;
4.configurable(可配置属性);------表明是否可以删除或修改该属性;(控制writable,enumerable属性)

var o={
name:"zhang",
y:26,
get age(){
return this.y;
},
set age(newV){
this.y=newV;
}
}
console.info(o.age);//26;
o.age=20;
console.info(o.y);//20;
console.info(o.age);//20;

设置属性
属性设置分为几种情况:1.如果要设置的属性是对象中不存在的(原型链和对象本身都没有),则相当于给对象创建了一个自有属性;2.如果要设置的属性在原型链中存在且writable为false,则不能设置该属性;3.如果要设置的属性是自有属性,不是继承而来的,则修改这个自有属性;4.如果要设置的属性在原型链中存在且是具有setter方法的访问器属性,那么这时将调用setter方法而不是给对象创建一个自有属性,需要注意的是setter方法是由对象来调用的,而不是定义这个属性的原型对象调用的。因此setter方法定义任意属性,这个操作只是针对对象本身,而不会修改原型链。5.如果要设置的属性在原型链中,且writable为true,则相当于为对象创建一个自有属性,覆盖了原型链上的同名属性。6.如果要设置的属性在原型链中,且为访问器属性,但是没有setter方法,则不能设置该属性。
总结:属性设置的结果包括:设置不成功;为对象创建一个属性;修改对象上原有的属性;一个例外(上述第四种情况);
规律特性:设置属性时,首先判断原型链,以此判断是否允许赋值操作;

3.枚举所有的自有属性,不仅仅是可枚举的属性

var o={x:2};
Object.defineProperty(o,"y",{value:3});
Object.keys(o);//["x"];

对象属性


对象是由无序的名/值对(属性)组成;属性名可以是包括空字符串在内的任意字符串;

属性分为数据属性和存取器属性;

例子

var o=Object.create(null);
console.info(Object.getPrototypeOf(o));//undefined;
//下面三种写法是等价的
var o=Object.create(Object.prototype);
var o={};
var o=new Object();

function Person(name){
this.name=name;
};
Person.prototype.eat = function(){
console.info("eat");
};
var p=Object.create(Person.prototype);
console.info(p.constructor);//Person;

var o=Object.create(Object.prototype,{
      name:{
        writable:true,
        value:"zhang",
        enumerable:true,
        configurable:false
      }
});
for(var i in o){
console.info(i);//name
};

//简单的实现原型继承
function inherit(p){
  if(p==null){
  throw TypeError();
  }else if(typeof p !=="object"&&typeof p !=="function"){
  throw TypeError();
  };
  if(Object.create){
    return Object.create(p);
  }else{
  function f(){};
  f.prototype=p;
  f.prototype.constructor=f;
  return new f();
  }
}
var o={};
Object.defineProperty(o,"name",{value:"zhang",writable:false,enumerable:false,configurable:true});
console.info(o.name);//"zhang";
//当writable为false时不能修改属性的值
o.name="wang";
console.info(o.name);//"zhang";

3.检测自有属性中的可枚举属性


对象本身也拥有三个特性;
1.对象的原型:指向另一个对象,本对象的属性继承自它的原型对象。
2.对象的类(class):一个标识对象类型的字符串。
3.对象的扩展标记:指明了是否可以向该对象添加新属性。

用法:writable特性控制是否可以修改value的值;configurable特性控制是否可以修改enumerable和writable特性,但是如果writable为true时,可以修改为false,反之则不可;当configurable为false时,不能修改为true;

对象的类属性用来表示对象的类型信息,ES3,ES5都未提供设置这个属性的方法,并只有一种间接的方法可以查询它。Object.prototype.toString();
toString方法大多被重写了,所以要使用Function.call()来调用Object.prototype.toString;

冻结对象(frozen)
Object.freeze();
Object.isFrozen();
这个方法可以将对象设置为不可扩展的,还可以将对象的所有自有属性设置为不可配置的,还可以将对象的所有数据属性设置为只读(如果对象的存取器属性具有setter方法,存取器属性不受影响,仍然可以使用属性赋值调用他们);

preventExtensions(),seal(),freeze()三个方法都返回一个新对象,所以可以链式的调用

属性特性

删除属性
delete操作符可以删除对象的自有属性,它的操作数应当是一个属性访问表达式。delete只是断开属性和宿主对象的联系,而不会去操作属性中的属性;

var o={};
Object.isExtensible(o);//true;
//第一种情况
var o={};
o.x="zhang";
console.info(o);//{x: "zhang"}
//第二种情况
var p={};
Object.defineProperty(p,"x",{value:"zhang",writable:false});
var o=Object.create(p);
o.x="wang";
console.info(o.x);//"zhang";
//第三种情况
var o={x:"zhang"};
o.x="wang";
console.info(o.x);//"wang";
//第四种情况
var p={
"age":25,
get x(){
return "zhang";
},
set x(name){
this.name=name;
}
};
var o=Object.create(p);
o.x="wang";
console.info(o.x);//"zhang";
console.info(o.name);//"wang";setter内部创建了一个name属性
//第五种情况
var p={};
Object.defineProperty(p,"x",{value:"zhang",writable:true});
var o=Object.create(p);
o.x="wang";
console.info(o.x);//"wang";
console.info(p.x);//"zhang";
//第六种情况
var p={
"age":25,
get x(){
return "zhang";
}
};
var o=Object.create(p);
o.x="wang";
console.info(o.x);//"zhang";
//创建一个封闭对象,包括一个冻结的原型和一个不可枚举的属性
var o=Object.seal(Object.create(Object.freeze({x:1}),{y:{value:2}}));

存取器属性有四个特性:
1.get属性(读取);
2.set属性(写入);
3.enumerable(可枚举属性);------表明该属性是否可以通过for..in循环返回该属性;
4.configurable(可配置属性);------表明是否可以删除或修改该属性;

枚举属性
有三种方式可以枚举属性:1.for in 循环;2.Object.keys();3.Object.getOwnPropertyNames();
分以下几种情况
1.枚举自有属性和继承属性(enumerable为true)

本文由彩世界开奖app官网发布于前端技术,转载请注明出处:ES6之主要知识点(七)对象彩世界平台官方网址

关键词: 日记本 ES6 JavaScr...