全面学习javascript中的对象
对象的基础
对象的定义
对象是一组由若干个无序的键值对(key/value)组成的数据集合 ,在 javascript 中所有的数据都可以被视作对象。每一个键值对又可以叫做“成员(members)”。
对象(object)的创建(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。
getter property 当访问一个对象属性时,会隐式的调用一个函数,返回一个生成值。
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}
与属性特性相关的方法
Object.defineProperty(obj, 'prop', descriptor) 定义或修改一个属性
Object.defineProperties(obj, props) 定义或修改多个属性
Object.create(proto, properiesObject ) 创建一个新的对象
对象的内部属性(internal slots)
对象的内部属性只是用来描述对象的相关信息、不属于对象的真正的属性,不可以访问。你可以把它当做特殊的隐藏属性。
[[]prototype]] obejct 表示对象的父对象,直接继承的对象。
[[extensible]] boolean 表示是否可以添加属性
[[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) // 读取自身没有的属性,会在原型链上找到最近的返回
需要注意的是,点运算符与方括号的不同点:
方括号运算符可以使用表达式。
方括号可以读取键名为数字、不符合标识符条件的、关键字和保留字的属性。
读取一个不存在的属性,返回的是 undefined 。可以利用这一点用来判断变量是否声明。
if(a in window){ // a 声明过}else{ // a 未声明}
添加属性(add property)
- 点运算符和方括号运算符不仅可以读取属性,还可以对属性进行赋值。
var me = { name: 'qingzhui'};me.age = 26; // 使用点运算符添加 age 属性me['like'] = 'music'; // 使用方括号运算符添加 like 属性
- Object.defineProperty() ES5 的方法,用来新增或者修改一个已经存在的属性。
var me = { name: 'qingzhui'};Object.defineProperty(me, 'age', { value: 26, writable: true, // 不定义,默认 false enumerable: true, // 不定义,默认 false configurable: true // 不定义,默认 false});
- 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"]
遍历的是对象所有可遍历(enumberable)的属性,会跳过不可遍历的属性
它不仅遍历对象自身的属性,还遍历继承的属性
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"]
检查属性是否存在
- hasOwnProperty() 如果自身含有这个属性,返回 true,否则 false。
var me = { name: 'qingzhui'};console.log(me.hasOwnProperty('name')); // trueconsole.log(me.hasOwnProperty('age')); // fasle
- 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 属性
对象的分类
- 标准对象(standard object)
如 Object、Aaary等
- 宿主对象(hosted object)
如DOM中的 document,BOM中的 window ,nodejs中的 http 。
- 自定义对象(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面向对象编程(三):非构造函数的继承
定义对象的父对象
使用 Object.create(myparent, )
定义一个没有 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 的值是什么?
- 当一个函数被当做一个对象的方法调用时,this 的值是指调用这个函数的对象。
var f = function(){ return this;};var o = { f1: f}; // this 是 oconsole.log(o == o.f1()); // true
- 当一个函数,使用 new 调用, this 的值是这个新创建的对象。
var F = function(){ this.name = 'qingzhui';};var me = new F(); // this 是 meconsole.log(me); // { name: 'qingzhui'}
- 当一个函数,是在全局上下文直接调用,如果是严格模式,this 的值是 undefined 。非严格模式下是全局对象(如 window)。
"use strict"var f = function(){ return this;};console.log(f()); // this 是 undefined
- 当一个函数是在一个函数里面,函数被调用时,如果是严格模式,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 是如何工作的?
每一个函数都有一个属性叫做原型属性(prototype)
它的值默认是{ constructor: F}
创建一个新的空对象,将它的父对象设置为 F.prototype
执行构造函数,把 this 指向这个新对象
如果构造函数没有返回值,或者返回的不是一个对象,那么 新对象 将作为返回值。如果返回的是一个对象,那么返回值为这个对象。
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 创建的对象的父对象是什么?
如果构造函数F返回的不是一个对象,或者没有返回值,那么它的父对象只指 F.prototype
如果构造函数F有返回语句,返回一个对象,要看返回的对象是怎么创建的。来判断它的父对象。
继承
全面理解面向对象的 JavaScript
文章同时发表在:
http://blog.qingzhui.net/post...
关键字:JavaScript, object
版权声明
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处。如若内容有涉嫌抄袭侵权/违法违规/事实不符,请点击 举报 进行投诉反馈!