资讯专栏INFORMATION COLUMN

全面学习javascript中的对象

leo108 / 3244人阅读

摘要:表示对象的父对象,直接继承的对象。的目的是让函数隐式的使用对象。内置的构造函数在中,有几个内置的构造函数,可以直接拿来使用。如果返回的是一个对象,那么返回值为这个对象。

对象的基础 对象的定义

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

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

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

构造函数

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

</>复制代码

  1. //方式1
  2. var me = {
  3. name: "qingzhui",
  4. age: 25
  5. };
  6. //方式2
  7. var me = new Object();
  8. me.name = "qingzhui";
  9. me.age = 25;
  10. //方式3
  11. var me = Object.create(Object.prototype, {
  12. name: {
  13. value: "qingzhui",
  14. enumerable: true,
  15. wriable: true,
  16. configurable: true
  17. },
  18. age: {
  19. value: 25,
  20. enumerable: true,
  21. wriable: true,
  22. configurable: true
  23. }
  24. });
键名(key),成员的名称

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

</>复制代码

  1. var obj = {
  2. 1: "name", // 数字可以不加引号
  3. "2name": "name2" // 不符合条件的,必须加引号
  4. };
键名(key),属性

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

属性的分类

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

数据属性(data property)

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

访问属性(accessor property)

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

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

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

</>复制代码

  1. var me = {
  2. name: "qingzhui",
  3. _age: 26,
  4. get age(){
  5. return "您真的年龄是:" + _age;
  6. }, // 语法 get property_name(){ statement }
  7. set age(num){
  8. return _age = num + 2;
  9. } // 语法 property_name(parameter_name) { statement }
  10. };
  11. me.age = 28;
  12. 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, 表示这个属性_是否可以在循环属性中被枚举_。

</>复制代码

  1. var me = {
  2. name: "qingzhui",
  3. };
  4. console.log(me.propertyIsEnumerable("name")); // true
configurable

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

Object.getOwnPropertyDescriptor(obj, "prop")

</>复制代码

  1. var o1 = Object.create(Object.prototype, {
  2. "name": {
  3. value: "qingzhui"
  4. }
  5. });
  6. var o2 = {
  7. name: "qingzhui"
  8. };
  9. console.log(Object.getOwnPropertyDescriptor(o1, "name"));
  10. //{configurable: false,enumerable: false,value: "qingzhui",writable: false}
  11. console.log(Object.getOwnPropertyDescriptor(o2, "name"));
  12. //{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)

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

</>复制代码

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

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

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

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

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

</>复制代码

  1. if(a in window){
  2. // a 声明过
  3. }else{
  4. // a 未声明
  5. }
添加属性(add property)

点运算符和方括号运算符不仅可以读取属性,还可以对属性进行赋值。

</>复制代码

  1. var me = {
  2. name: "qingzhui"
  3. };
  4. me.age = 26; // 使用点运算符添加 age 属性
  5. me["like"] = "music"; // 使用方括号运算符添加 like 属性

Object.defineProperty() ES5 的方法,用来新增或者修改一个已经存在的属性。

</>复制代码

  1. var me = {
  2. name: "qingzhui"
  3. };
  4. Object.defineProperty(me, "age", {
  5. value: 26,
  6. writable: true, // 不定义,默认 false
  7. enumerable: true, // 不定义,默认 false
  8. configurable: true // 不定义,默认 false
  9. });

Object.defineProperties() ES5的方法,用来新增或者修改多个自有属性,并返回该对象。

</>复制代码

  1. var me = {
  2. name: "qingzhui"
  3. };
  4. Object.defineProperties(me, {
  5. "age": {
  6. value: 26
  7. },
  8. "sex": {
  9. value: "boy",
  10. wriable: false,
  11. enumerable: true,
  12. configurable: false
  13. }
  14. });
修改属性(modify property)

</>复制代码

  1. var me = {
  2. name: "qingzhui"
  3. };
  4. me.name = "scl"; // 可以使用点运算符 对 name 属性重新赋值,达到修改的目的
删除属性(delete property)

使用 [delete](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/delete) 运算符,可以删除对象的属性,在严格模式下,删除一个不可配置的属性(non-configurable),会抛出异常,在非严格模式下,返回 false,其它情况都返回 true

</>复制代码

  1. var me = {
  2. name: "qingzhui"
  3. };
  4. delete me.name; // true
遍历对象的属性 for-in

可以使用 in 运算符,来判断某个属性是否在指定的对象中。用[for-in](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Statements/for...in),任意序迭代一个对象的可枚举属性。每个不同的属性,语句都会被执行一次。

</>复制代码

  1. //创建 person 对象
  2. var person = {
  3. species: "动物",
  4. sex: "男"
  5. };
  6. //创建 me 对象,让其 继承 person
  7. var me = Object.create(person, {
  8. name: {
  9. value: "qingzhui",
  10. wriable: true,
  11. enumerable: true, // 设置可枚举
  12. configurable: true
  13. },
  14. age: {
  15. value: 26,
  16. wriable: true,
  17. enumerable: false, // 设置不可枚举
  18. configurable: true
  19. }
  20. });
  21. var arr = [];
  22. for(var a in me){
  23. arr.push(a);
  24. }
  25. console.log(arr); // ["name", "species", "sex"]

遍历的是对象所有_可遍历(enumberable)的属性_,会跳过不可遍历的属性

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

Object.keys() es5方法

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

</>复制代码

  1. console.log(Object.keys(me)); // ["name"]
Object.getOwnPropertyNames(obj) ES5方法

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

</>复制代码

  1. console.log(Object.getOwnPropertyNames(me)); // ["name", "age"]
检查属性是否存在

hasOwnProperty() 如果自身含有这个属性,返回 true,否则 false。

</>复制代码

  1. var me = {
  2. name: "qingzhui"
  3. };
  4. console.log(me.hasOwnProperty("name")); // true
  5. console.log(me.hasOwnProperty("age")); // fasle

in 运算符,用来判断自身或者继承来的属性是否在这个对象中。

</>复制代码

  1. var person = {
  2. species: "动物",
  3. sex: "男"
  4. }
  5. var me = Object.create(person);
  6. me.name = "qingzhui";
  7. console.log("name" in me); // 检查自身的属性 true
  8. console.log("sex" in me); // 检查继承的属性 true
  9. console.log("job" in me); // 检查没有的属性 fasle
对象的引用

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

</>复制代码

  1. var me = {
  2. name: "qingzhui"
  3. };
  4. var qingzhui = me; // 让 qingzhui 引用 me 对象
  5. qingzhui.name = "scl"; // 修改 qingzhui 的 name 属性
  6. 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]] 指向同一个对象,即它的原型对象(父对象)。

</>复制代码

  1. funtion Person(){
  2. //
  3. }
  4. var me = new Person();
  5. console.log(me.__proto__ === Person.prototype); // true
getPrototypeOf()

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

</>复制代码

  1. Object.getPrototypeOf(object)
isPrototypeOf()

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

</>复制代码

  1. obj.prototype.isPrototypeOf(object)
资源

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

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

定义对象的父对象

使用 Object.create(myparent, )

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

限制对象的一些方法

</>复制代码

  1. Object.isExtensible() // 判断是否可扩展
  2. Object.preventExtensions()
  3. Object.isSeal() // 判断是否密封
  4. Object.seal()
  5. Object.isFrozen() // 判断是否冻结
  6. Object.freeze()
确定对象的子类型

</>复制代码

  1. Object.prototype.toString.call(myObj);
  2. console.log(Object.prototype.toString.call({})) // "[object Object]"
复制对象

方法一(深拷贝)

</>复制代码

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

方法二 (es6)

</>复制代码

  1. Object.assign(target, ...sources)

javascript中的深拷贝和浅拷贝?

深入剖析 JavaScript 的深复制

判断对象是否相等

</>复制代码

  1. function is_obj_equal(obj1, obj2){
  2. var keys1 = Object.keys(obj1).sort();
  3. var keys2 = Object.keys(obj2).sort();
  4. if(keys1.length !== keys2.length){
  5. return false;
  6. }
  7. if (!keys1.every(function(k, i){ return (k === keys2[i]); })){
  8. return false;
  9. }
  10. return keys1.every(function(kk) {
  11. var v1 = obj1[kk];
  12. var v2 = obj2[kk];
  13. if ( Array.isArray(v1) ) {
  14. return is_array_equal(v1,v2);
  15. } else if ( typeof v1 === "object" && v1 !== null) {
  16. return is_obj_equal(v1,v2);
  17. } else {
  18. return v1 === v2;
  19. }
  20. });
  21. }
面向对象编程 this

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

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

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

this 的值是什么?

当一个函数被当做一个对象的方法调用时,this 的值是指调用这个函数的对象。

</>复制代码

  1. var f = function(){
  2. return this;
  3. };
  4. var o = { f1: f}; // this 是 o
  5. console.log(o == o.f1()); // true

当一个函数,使用 new 调用, this 的值是这个新创建的对象。

</>复制代码

  1. var F = function(){
  2. this.name = "qingzhui";
  3. };
  4. var me = new F(); // this 是 me
  5. console.log(me); // { name: "qingzhui"}

当一个函数,是在全局上下文直接调用,如果是严格模式,this 的值是 undefined 。非严格模式下是全局对象(如 window)。

</>复制代码

  1. "use strict"
  2. var f = function(){
  3. return this;
  4. };
  5. console.log(f()); // thisundefined

当一个函数是在一个函数里面,函数被调用时,如果是严格模式,this 的值是 undefined ,否则是全局对象

</>复制代码

  1. "use stric"
  2. var f = function(){
  3. var h = function(){
  4. return this; // thisundefined
  5. };
  6. return h();
  7. };
  8. console.log(f() === undefined); // true
  9. var o = {
  10. p = function(){
  11. var f = function(){
  12. return this; // thisundefined
  13. };
  14. return f();
  15. }
  16. };
  17. console.log(o.p() === undefined); // true
资源

js 中 this 关键字详解

详解this

构造函数(constructor)

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

内置的构造函数

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

</>复制代码

  1. var o = new Object();
  2. var arr = new Array();
  3. var fun = new Function();
  4. var date = new Date();
  5. var reg = new Regex();
原始类型值的包装器

</>复制代码

  1. var str = new String("a");
  2. var num = new Number(1);
  3. var boolean = new Boolean(true);

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

原型属性(prototype)

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

</>复制代码

  1. var f = function(){
  2. };
  3. console.log(f.hasOwnProperty("prototype")); // true
  4. console.log(Object.hasOwnProperty("prototype")); // true
  5. console.log(Array.hasOwnProperty("prototype")); // true

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

</>复制代码

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

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

</>复制代码

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

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

操作符 new

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

</>复制代码

  1. // 语法
  2. new function_name(args);
new 是如何工作的?

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

它的值默认是{ constructor: F}

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

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

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

</>复制代码

  1. var F1 = function(){
  2. this.name = 1;
  3. };
  4. var F2 = function(){
  5. this.name = 2;
  6. return 3;
  7. };
  8. var F3 = function(){
  9. this.name = 3;
  10. return {
  11. name: "qingzhui"
  12. };
  13. };
  14. var f1 = new F1(); // { name: 1}
  15. var f2 = new F2(); // { name: 2}
  16. var f3 = new F3(); // { name: "qingzhui"}
使用 new 创建的对象的父对象是什么?

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

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

继承

全面理解面向对象的 JavaScript

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

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/91623.html

相关文章

  • H5学习

    摘要:为此决定自研一个富文本编辑器。本文,主要介绍如何实现富文本编辑器,和解决一些不同浏览器和设备之间的。 对ES6Generator函数的理解 Generator 函数是 ES6 提供的一种异步编程解决方案,语法行为与传统函数完全不同。 JavaScript 设计模式 ② 巧用工厂模式和创建者模式 我为什么把他们两个放在一起讲?我觉得这两个设计模式有相似之处,有时候会一个设计模式不能满...

    aristark 评论0 收藏0
  • 前端开发周报: CSS 布局方式与JavaScript数据结构和算法

    摘要:如果没有学习过计算机科学的程序员,当我们在处理一些问题时,比较熟悉的数据结构就是数组,数组无疑是一个很好的选择。 showImg(https://segmentfault.com/img/bVTSjt?w=400&h=300); 1、常见 CSS 布局方式详见: 一些常见的 CSS 布局方式梳理,涉及 Flex 布局、Grid 布局、圣杯布局、双飞翼布局等。http://cherryb...

    huhud 评论0 收藏0
  • 前端开发周报: CSS 布局方式与JavaScript数据结构和算法

    摘要:如果没有学习过计算机科学的程序员,当我们在处理一些问题时,比较熟悉的数据结构就是数组,数组无疑是一个很好的选择。 showImg(https://segmentfault.com/img/bVTSjt?w=400&h=300); 1、常见 CSS 布局方式详见: 一些常见的 CSS 布局方式梳理,涉及 Flex 布局、Grid 布局、圣杯布局、双飞翼布局等。http://cherryb...

    ?xiaoxiao, 评论0 收藏0

发表评论

0条评论

leo108

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<