全面学习javascript中的对象

对象的基础

对象的定义

对象是一组由若干个无序的键值对(key/value)组成的数据集合 ,在 javascript 中所有的数据都可以被视作对象。每一个键值对又可以叫做“成员(members)”。

对象(object)的创建(3种方式)

  1. 对象字面量(对象初始化器)

  2. 构造函数

  3. Object.create() es5的创建对象的方式,可以指定原型对象

//方式1var me = {    name: 'qingzhui',    age: 25};//方式2var me = new Object();me.name = 'qingzhui';me.age = 25;//方式3var me = Object.create(Object.prototype, {    name: {        value: 'qingzhui',        enumerable: true,        wriable: true,        configurable: true    },    age: {        value: 25,        enumerable: true,        wriable: true,        configurable: true    }});

键名(key),成员的名称

键名,键值对中的 key,我们可以将之称为成员的名称。对象中所有的键名都是字符串,所有加不加引号都可以。必须要加引号的情况:如果键名不是数字,又不符合标识符的条件,就必须加上引号。

var obj = {    1: 'name', // 数字可以不加引号    "2name": 'name2' // 不符合条件的,必须加引号};

键名(key),属性

键名,又可以称作属性(property)。它的键值_可以是任何数据类型,_如果它的值是一个函数的话,我们可以把这个属性叫做方法(method)

属性的分类

属性有两种类型:数据属性(data property)、访问属性(accessor property)。

数据属性(data property)

除开访问属性(get/set)之外,都是数据属性。

访问属性(accessor property)

访问属性又叫 geter/seter 属性。它只有2种 getter property / setter property。

  1. getter property 当访问一个对象属性时,会隐式的调用一个函数,返回一个生成值。

  2. setter property 当赋值一个对象属性时,会隐式的调用一个函数,返回一个生成值。

var me = {    name: 'qingzhui',    _age: 26,    get age(){        return '您真的年龄是:' + _age;    }, // 语法 get property_name(){ statement }    set age(num){        return _age = num + 2;    } // 语法 property_name(parameter_name) { statement }};me.age = 28;console.log(me.age); // "您真的年龄是:30"

根据属性的所属,可以把属性分为两种自身属性(own property)、继承属性(inherited property)。

自身属性(own property)

就是在对象自身定义的属性,我们称之为自身属性。

继承属性(inherited property)

通过原型链(prototype chain),继承自父对象、或是祖先对象的属性,我们称之为继承属性。

属性的特性(property attribute)

属性的特性,用来描述属性的相关信息。在数据属性中,属性拥有4(writable、enumerable、configurable、value)种特性,用来表示这个属性的相关信息。在访问属性中,get 属性拥有3(get、enumerable、configurable)种特性,set属性拥有3(set、enumerable、configurable)种特性。

value

属性的属性值。

wriable

true 或者 false,表示这个属性是否可以设置

enumerable

true 或者 false, 表示这个属性是否可以在循环属性中被枚举

var me = {    name: 'qingzhui',};console.log(me.propertyIsEnumerable('name')); // true

configurable

true 或者 false,表示这个属性是否可以被删除或者属性值是否可以改变

Object.getOwnPropertyDescriptor(obj, 'prop')

var o1 = Object.create(Object.prototype, {    'name': {        value: 'qingzhui'    }});var o2 = {    name: 'qingzhui'};console.log(Object.getOwnPropertyDescriptor(o1, 'name'));//{configurable: false,enumerable: false,value: "qingzhui",writable: false}console.log(Object.getOwnPropertyDescriptor(o2, 'name'));//{configurable: true, enumerable: true, value: "qingzhui", writable: true}

与属性特性相关的方法

  1. Object.defineProperty(obj, 'prop', descriptor) 定义或修改一个属性

  2. Object.defineProperties(obj, props) 定义或修改多个属性

  3. Object.create(proto, properiesObject ) 创建一个新的对象

对象的内部属性(internal slots)

对象的内部属性只是用来描述对象的相关信息、不属于对象的真正的属性,不可以访问。你可以把它当做特殊的隐藏属性。

  1. [[]prototype]] obejct 表示对象的父对象,直接继承的对象。

  2. [[extensible]] boolean 表示是否可以添加属性

  3. [[class]] string 表示对象的分类

属性的操作

读取属性(read property)

读取属性有两种方法,一种是点运算符,一种是方括号运算符

var me = {    name: 'qingzhui';};//方式1console.log(me.name); // 'qingzhui'//方式2console.log(me['name']); // 'qingzhui'console.log(me.age); // 读取一个不存在的属性返回 'undefined'console.log(me.toSting) // 读取自身没有的属性,会在原型链上找到最近的返回

需要注意的是,点运算符与方括号的不同点

  1. 方括号运算符可以使用表达式。

  2. 方括号可以读取键名为数字、不符合标识符条件的、关键字和保留字的属性。

读取一个不存在的属性,返回的是 undefined 。可以利用这一点用来判断变量是否声明。

if(a in window){    // a 声明过}else{    // a 未声明}

添加属性(add property)

  1. 点运算符和方括号运算符不仅可以读取属性,还可以对属性进行赋值。
var me = {    name: 'qingzhui'};me.age = 26; // 使用点运算符添加 age 属性me['like'] = 'music'; // 使用方括号运算符添加 like 属性
  1. Object.defineProperty() ES5 的方法,用来新增或者修改一个已经存在的属性。
var me = {    name: 'qingzhui'};Object.defineProperty(me, 'age', {    value: 26,    writable: true, // 不定义,默认 false    enumerable: true, // 不定义,默认 false    configurable: true // 不定义,默认 false});
  1. Object.defineProperties() ES5的方法,用来新增或者修改多个自有属性,并返回该对象。
var me = {    name: 'qingzhui'};Object.defineProperties(me, {    'age': {        value: 26    },    'sex': {        value: 'boy',        wriable: false,        enumerable: true,        configurable: false    }});

修改属性(modify property)

var me = {    name: 'qingzhui'};me.name = 'scl'; // 可以使用点运算符 对 name 属性重新赋值,达到修改的目的

删除属性(delete property)

使用 delete 运算符,可以删除对象的属性,在严格模式下,删除一个不可配置的属性(non-configurable),会抛出异常,在非严格模式下,返回 false,其它情况都返回 true 。

var me = {    name: 'qingzhui'};delete me.name; // true

遍历对象的属性

for-in

可以使用 in 运算符,来判断某个属性是否在指定的对象中。用for-in,以任意序迭代一个对象的可枚举属性。每个不同的属性,语句都会被执行一次。

//创建 person 对象var person = {    species: "动物",    sex: '男'};//创建 me 对象,让其 继承 personvar me = Object.create(person, {    name: {        value: 'qingzhui',        wriable: true,        enumerable: true, // 设置可枚举        configurable: true    },    age: {        value: 26,        wriable: true,        enumerable: false, // 设置不可枚举        configurable: true    }});var arr = [];for(var a in me){    arr.push(a);}console.log(arr); // ["name", "species", "sex"]
  1. 遍历的是对象所有可遍历(enumberable)的属性,会跳过不可遍历的属性

  2. 它不仅遍历对象自身的属性,还遍历继承的属性

Object.keys() es5方法

使用 Object.keys(obj) 可以遍历自身所有可以枚举的属性,返回所有可枚举自身属性的属性名组成的数组。

console.log(Object.keys(me)); // ["name"]

Object.getOwnPropertyNames(obj) ES5方法

使用 Object.getOwnPropertyNames(obj) 可以遍历自身所有的属性,返回所有自身属性的属性名组成的数组。

console.log(Object.getOwnPropertyNames(me)); // ["name", "age"]

检查属性是否存在

  1. hasOwnProperty() 如果自身含有这个属性,返回 true,否则 false。
var me = {    name: 'qingzhui'};console.log(me.hasOwnProperty('name')); // trueconsole.log(me.hasOwnProperty('age')); // fasle
  1. in 运算符,用来判断自身或者继承来的属性是否在这个对象中。
var person = {    species: "动物",    sex: '男'}var me = Object.create(person);me.name = 'qingzhui';console.log('name' in me); // 检查自身的属性 trueconsole.log('sex' in me); // 检查继承的属性 trueconsole.log('job' in me); // 检查没有的属性 fasle

对象的引用

对象的引用是按址引用的,如果不同的变量引用同一个对象,它们会指向同一个内存地址,修改 其中一个变量,会影响到其它的变量。

var me = {    name: 'qingzhui'};var qingzhui = me; // 让 qingzhui 引用 me 对象qingzhui.name = 'scl'; // 修改 qingzhui 的 name 属性console.log(me.name); // 'scl' 改变了 me 的 name 属性  

对象的分类

  1. 标准对象(standard object)

如 Object、Aaary等

  1. 宿主对象(hosted object)

如DOM中的 document,BOM中的 window ,nodejs中的 http 。

  1. 自定义对象(user-define object)

如 var o = {};

对象深入

原型和继承

原型(prototype)

在 javascript 中,每一个对象都有一个内部的相关信息叫 prototype ,可以用 [[prototype]]表示。

[[prototype]]的值是一个对象或者是 null ,我们把这个对象称之为原型对象,或者说是父对象。

继承(inheritance)

在 javascript 中,查找属性的时候,先从自身查找,如果找不到,就在其父对象,一直往上找,直到 null,这种机制就叫做继承

原型链(prototype chain)

一个对象的父对象,父对象的父对象,形成一个链,称之为原型链(prototype chain)

不是所有的对象都有父对象,Object.prototype 是所有对象的根,它的原型对象(父对象)是 null。

查找对象的原型对象(父对象)

proto

返回对象的原型对象(父对象),在 ES6 之前,只有部分浏览器支持,在ES6 被正式纳入标准。
_proto 和 [[prototype]] 指向同一个对象,即它的原型对象(父对象)。

funtion Person(){    //}var me = new Person();console.log(me.__proto__ === Person.prototype); // true

getPrototypeOf()

返回指定对象的原型对象。

Object.getPrototypeOf(object)

isPrototypeOf()

测试一个对象是否存在于另一个对象的原型链上。

obj.prototype.isPrototypeOf(object)

资源

从本质认识JavaScript的原型继承和类继承

Javascript面向对象编程(三):非构造函数的继承

定义对象的父对象

  1. 使用 Object.create(myparent, )

  2. 定义一个没有 return 的构造函数 F,然后 F.prototype = myparent,使用 new F()

限制对象的一些方法

Object.isExtensible()  // 判断是否可扩展Object.preventExtensions()Object.isSeal() // 判断是否密封Object.seal()Object.isFrozen() // 判断是否冻结Object.freeze()

确定对象的子类型

Object.prototype.toString.call(myObj);console.log(Object.prototype.toString.call({})) // "[object Object]"

复制对象

方法一(深拷贝)

Json.parse(Json.stringify(obj));

方法二 (es6)

Object.assign(target, ...sources)

javascript中的深拷贝和浅拷贝?

深入剖析 JavaScript 的深复制

判断对象是否相等

function is_obj_equal(obj1, obj2){    var keys1 = Object.keys(obj1).sort();    var keys2 = Object.keys(obj2).sort();    if(keys1.length !== keys2.length){        return false;    }    if (!keys1.every(function(k, i){ return (k === keys2[i]); })){        return false;    }    return keys1.every(function(kk) {        var v1 = obj1[kk];        var v2 = obj2[kk];        if ( Array.isArray(v1) )  {            return is_array_equal(v1,v2);        } else if ( typeof v1 === "object" && v1 !== null) {            return is_obj_equal(v1,v2);        } else {            return  v1 === v2;        }    });}

面向对象编程

this

在 javascript 中,当一个函数被调用时,它有一个相关值被称之为 ‘ ThisBinding ’。

在函数定义时,‘ ThisBinding ’ 是用 this 表示。

‘ ThisBinding’ 的目的是让函数隐式的使用对象。

this 的值是什么?

  1. 当一个函数被当做一个对象的方法调用时,this 的值是指调用这个函数的对象。
var f = function(){    return this;};var o = { f1: f}; // this 是 oconsole.log(o == o.f1()); // true
  1. 当一个函数,使用 new 调用, this 的值是这个新创建的对象。
var F = function(){    this.name = 'qingzhui';};var me = new F(); // this 是 meconsole.log(me); // { name: 'qingzhui'}
  1. 当一个函数,是在全局上下文直接调用,如果是严格模式,this 的值是 undefined 。非严格模式下是全局对象(如 window)。
"use strict"var f = function(){    return this;};console.log(f()); // this 是 undefined
  1. 当一个函数是在一个函数里面,函数被调用时,如果是严格模式,this 的值是 undefined ,否则是全局对象
"use stric"var f = function(){    var h = function(){        return this; // this 是 undefined    };    return h();};console.log(f() === undefined); // truevar o = {    p = function(){        var f = function(){            return this; // this 是 undefined        };        return f();    }};console.log(o.p() === undefined); // true

资源

js 中 this 关键字详解

详解this

构造函数(constructor)

当一个函数被设计使用 new 调用的时候,我们叫这个函数为构造函数。构造函数是用来创建函数的一种方式。

内置的构造函数

在 JavaScript 中,有几个内置的构造函数,可以直接拿来使用。

var o = new Object();var arr = new Array();var fun = new Function();var date = new Date();var reg = new Regex();

原始类型值的包装器

var str = new String('a');var num = new Number(1);var boolean = new Boolean(true);

构造函数应该已大写字母开始。

原型属性(prototype)

在 JavaScript 中,每一个函数有一个特殊的属性 prototype 。

var f = function(){};console.log(f.hasOwnProperty('prototype')); // trueconsole.log(Object.hasOwnProperty('prototype')); // trueconsole.log(Array.hasOwnProperty('prototype')); // true

用户自定义的函数,它的原型属性的值默认值:{ constructor: f}

var f = function(){};console.log(f.hasOwnProperty('prototype')); // trueconsole.log(Object.getOwnpropertyNames(f.prototype).lenght === 1); // trueconsole.log(Object.getOwnpropertyNames(f.prototype)[0] === constructor); // trueconsole.log(Object.getOwnPropertyDescriptor(f.protptype, 'constructor')); // { value: f, writable: true, enumerable: false, configurable: true}

内置的函数,它的原型属性的默认值是

Object.prototype 就是 Object.prototype, Object.prototype 被设计为 new Object()新对象的父对象

在严格模式下,内置的构造函数的原型属性不能被改变,否则会报错。

操作符 new

操作符 new 是用来和函数一起,创建一个对象。

// 语法new function_name(args);

new 是如何工作的?

  1. 每一个函数都有一个属性叫做原型属性(prototype)

  2. 它的值默认是{ constructor: F}

  3. 创建一个新的空对象,将它的父对象设置为 F.prototype

  4. 执行构造函数,把 this 指向这个新对象

  5. 如果构造函数没有返回值,或者返回的不是一个对象,那么 新对象 将作为返回值。如果返回的是一个对象,那么返回值为这个对象。

var F1 = function(){    this.name = 1;};var F2 = function(){    this.name = 2;    return 3;};var F3 = function(){    this.name = 3;    return {        name: 'qingzhui'    };};var f1 = new F1(); // { name: 1}var f2 = new F2(); // { name: 2}var f3 = new F3(); // { name: 'qingzhui'}

使用 new 创建的对象的父对象是什么?

  1. 如果构造函数F返回的不是一个对象,或者没有返回值,那么它的父对象只指 F.prototype

  2. 如果构造函数F有返回语句,返回一个对象,要看返回的对象是怎么创建的。来判断它的父对象。

继承

全面理解面向对象的 JavaScript

文章同时发表在:
http://blog.qingzhui.net/post...

关键字:JavaScript, object

版权声明

本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处。如若内容有涉嫌抄袭侵权/违法违规/事实不符,请点击 举报 进行投诉反馈!

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部