Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >JavaScript之面向对象的概念,对象属性和对象属性的特性简介

JavaScript之面向对象的概念,对象属性和对象属性的特性简介

作者头像
郑小超.
发布于 2018-01-24 07:15:39
发布于 2018-01-24 07:15:39
2.6K00
代码可运行
举报
文章被收录于专栏:GreenLeavesGreenLeaves
运行总次数:0
代码可运行

  一、大家都知道,面向对象语言有一个标志,那就是他们都有类的概念,通过类我们可以创建任意多个具有相同属性和方法的对象。但ECMAScript(指定JavaScript标准的机构,也就是说JavaScript是实现其标准的扩展)并没有类的概念,因此他的对象和基于类的语言中的对象有所不同,ECMAScript把对象定义为:"无需属性的集合,其属性可以包含基本值、对象或者函数"。严格的来说,这就相当于说对象是一组没有特定顺序的值。对象的每个属性或方法都有一个名字,而每个名字都映射到一个值。正应为这样,我们可以把ECMAScript的对象想象成散列表;无非就是一组键值对,其中值可以是数据或函数。每个对象都是基于一个引用类型创建的。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
        //JavaScript早期的对象定义方式
        var person = new Object();
        person.name = "张三";
        person.age = 22;
        person.job = "coder";
        person.sayName = function () {
            alert(this.name);
        }
        //几年后,对象字面量成为创建这种对象的首选模式
        var person = {
            name: "Nicholas",
            age: 22,
            job: "coder",
            sayName: function () {
                alert(this.name);
            }
        }
        person.sayName();

注意:这里的对象,不像真正的面向对象语言那样,对象真的被创建了,这里对象的概念只是一个数据集合(这个数据集合可以存放任何数据)的引用,这个引用值不会改变,而面向对象的类你每new一次,他的引用值都会改变一次。

二、面向对象的属性类型

在ES5中在定义只有内部采用的特性时,描述了属性(property)的各种特征。ECMA-262定义这些特性是为了实现JavaScript引擎用的,因此在JavaScript中不能直接访问他们,为了表示特性是内部值,ECMA-262规范把它们放在了两对方括号中,例如[[Enumerable]]。

ECMAScript中有两种属性:数据属性和访问器属性。

1、数据属性

数据属性包含一个数据值的位置。在这个位置可以读取和写入值。数据属性有4个描述其行为的特性。

(1)[[Configurable]]:表示能否通过delete删除属性从而重新定义属性,能否修改属性的特性,或者能否把属性修改为访问器属性。像上面代码中直接在对象上定义的属性,他们的这个特性默认值为true.

(2)[[Enumerable]]:表示能否通过for-in循环返回属性。像上面代码中直接在对象上定义的属性,他们的这个特性值默认为true。

(3)[[Writable]]:表示能否修改属性的值。像上面代码中直接在对象定义的属性,他们的这个特性默认为true。

(4)[[Value]]:包含这个属性的数据值。读取属性值的时候,从这个位置读;写入属性值的时候.把新值保存在这个位置。这个特性的默认值为undefined。也就是说如果你不给属性的该特性赋值,他的值将会是undefined。

现在有如下代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
var person={
     name:"张三"
}

像上面中直接在对象中定义的属性,他们的[[Configurable]]、[[Enumerable]]、[[Writable]]特性都被设置为true,而[[Value]]被设置为指定的值"张三";按照上面特性的描述,person对象中的name属性可以通过delete删除重新定义该属性,可以修改该属性的特性,可以把该属性修改为访问器属性。可以通过for-in循环返回属性,可以修改属性的值。

应为ECMA-262规范中提到属性的特性是为了实现JavaScript引擎所用到,所以我们不能通过JavaScript直接访问,但是JavaScript给我们提供了了一个方法,来操作我们需要操作的对象的属性的特性;这个方法是

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
        //这个方法接收三个参数:属性所在的对象引用、属性的名字和一个描述符对象
        //其中描述符对象的属性必须是上面提到的四个属性的特性(实现JavaScript引擎所用)
        //Configurable、Enumerable、Writable、value
        Object.defineProperty(); 

下面是这个方法的应用:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
        var person = {};
        Object.defineProperty(person, "name", {
          writable:false, //writable这个特性决定了当前属性的属性值能否被修改,这边设置为false,也就是不能被修改
          value:"张三"
      });
      alert(person.name);
      person.name = "李四";//所以给name重新赋值并没有效果,如果将writable的值修改为true,这边的赋值就会成功!
      alert(person.name);     

两次输出都是"张三"。

alert(person.name);

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
        var person = {};
        Object.defineProperty(person, "name", {
            configurable: true, //configurable这个特性决定了当前属性能否通过delete删除从而重新定义属性,能否修改属性的特性,能否将属性修改为访问器属性。
          //这边设置为true,所以都可以
          value:"张三"
      });
      alert(person.name);
      delete person.name;//所以当这边删除name属性后,person对象就不存在了name属性
      alert(person.name);//所以这边输出undefined因为此时person对象没有了name属性

输出:"张三","undefined";

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
        var person = {};
        Object.defineProperty(person, "name", {
            configurable: false, //configurable这个特性决定了当前属性能否通过delete删除从而重新定义属性,能否修改属性的特性,能否将属性修改为访问器属性。
          //这边设置为false,所以都不可以
            value:"张三"
      });
      alert(person.name);
      delete person.name;//所以当这边执行删除name属性的动作没有效果
      alert(person.name);//所以这边输出还是"张三"

输出:"张三","张三"

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
        var person = {};
        Object.defineProperty(person, "name", {
            configurable: false, //configurable这个特性决定了当前属性能否通过delete删除从而重新定义属性,能否修改属性的特性,能否将属性修改为访问器属性。
          //这边设置为false,所以name属性被设置成为无法配置的属性
          value:"张三",
      });
        Object.defineProperty(person, "name", {
            configurable: true, //报错      
            value:"张三",
      });

这边需要注意:当我们把属性定义为不给配置的之后,就不能再把它变回可配置的了。此时如果再调用Object.defineProperty()方法修改出writable之外的特性,都会导致错误。

输出:TypeError: can't redefine non-configurable property "name"

注意:当我们调用Object.defineProperty()方法,在指定了对象和对象的属性却没有指定描述符对象的的configurable、writable、Enumerbale的三个特性时,那么他们的默认值都为false;

综上所述:我们可以通过Object.defineProperty()方法来多次修改同一个属性,但是当我们把属性的configurable特性的值设置成false,就会有所限制了,我们只能修改属性的writable特性的值了;

2、访问器属性

访问器属性和数据属性的区别是:访问器属性不包含数据值,且类似与面向对象里面的类属性,他们都包含一对getter和setter函数,在读取访问器属性时,会调用getter函数,这个函数会返回有效的值,在写入访问器属性时,会调用setter函数并写入新值,这个函数负责决定如何处理数据,这个面向对象中的类属性大致一样!

访问器属性和数据属性一样,有4个特性:

[[Configurable]]:表示能否通过delete删除属性从而重新定义属性,能否修改属性的特性,或者能否把属性修改为数据属性,对于直接在对象上定义的属性,这个特性的默认值为true;

[[Enumerable]]:表示能否通过for-in循环返回属性。对于直接在对象上定义的属性。这个特性的默认值为true。

[[Get]]:在读取属性时调用的函数,默认值为undefined。

[[Set]]:在写入属性时调用的函数。默认值为undefined。

访问器属性不能直接定义,必须使用Object.definneProperty().请看下面代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
        var book = {
            _year: 1994,
            edition: 1
        }
        Object.defineProperty(book, "year", {
            get: function () {
                return this._year;
            },
            set: function (newValue) {
                if (newValue > 1994) {
                    this.edition += newValue - this._year;
                    this._year = newValue;
                }
            }
        });
        book.year = 2016;
        alert(book.edition);  

以上代码创建了一个book对象,并给他定义了两个默认的属性:_year和edition。_year前面的下划线十一找那个常用的标记,用于表示只能通过通过对象方法访问的属性。而访问器属性year则包含一个getter函数和setter函数。getter函数返回_year值.这里不一定要同时指定getter和setter。只指定getter意味着属性是不能写,只指定setter意味着只写,无法获取属性值。

注意:支持ECMAScript 5的get,set方法浏览器只有IE9+(IE8部分实现)、FireFox 4+、Safari 5+、Opera 12+和Chrome,在这之前,要创建访问器属性,一般都使用两个非标准方法,_defineGetter_()和_defineSetter_(),如下代码是早期访问器属性的代码版本:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
        var book = {
            _year: 1994,
            edition: 1
        }
        book._defineGetter_("year", function () {
            return this._year;
        });
        book._defineSetter_("year", function (newValue) {
            if (newValue > 1994) {
                this.edition += newValue - this._year;
            }
            this._year = newValue;
        });
        book.year = 2016;
        alert(book.edition);  

3、定义多个属性

在开发当中,当我们用到对象的时候,大多数情况下都会用到多个属性,所以ECMAScript 5又定义了一个Object.defineProperties()方法。利用这个方法可以通过描述符一次定义多个属性。

代码如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    var book = {};
    Object.defineProperties(book, {
        _year: {
            writable: true,
            value: 2004
        },
        edition: {
            writable: true,
            value: 1
        },
        year: {
            get: function () {
                return this._year;
            },
            set: function (newValue) {
                if (newValue > this._year) {
                    this.edition += newValue - this._year;
                }
                this._year = newValue;
            }
        }
    });
    book.year = 2016;
    alert(book.edition);

上面定义了两个数据属性(_year和edition)和一个访问器属性(year)。最终的对象和上一段代码定义的对象相同。唯一的区别是这里的属性都是在同一时间创建的!上一段代码中定义的对象,实在定义完数据属性之后又定义了一个访问器属性。

4、读取属性的特性

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    var book = {};
    Object.defineProperties(book, {
        _year: {
            writable: true,
            value: 2004
        },
        edition: {
            writable: true,
            value: 1
        },
        year: {
            get: function () {
                return this._year;
            },
            set: function (newValue) {
                if (newValue > this._year) {
                    this.edition += newValue - this._year;
                }
                this._year = newValue;
            }
        }
    });
    var attribute = Object.getOwnPropertyDescriptor(book, "_year"); /*获取数据属性_year对象注意:支持这个方法的浏览器有IE9+,fireFox4,Safari 5+,Opera,Chrome*/
    alert(attribute.value);  /*输出数据属性_year的Value特性*/
    alert(attribute.configurable); /*输出数据属性_year的configurable特性*/
    alert(typeof attribute.get); /*输出数据属性的get的特性,但是数据属性被没有Get特性,只有访问器属性才有Get和Set特性,所以这里输出undefined*/
    var attribute_two=Object.getOwnPropertyDescriptor(book,"year");
    alert(attribute_two.get); 
     //输出访问器属性的get方法,get是指向getter函数的指针
    alert(attribute_two.value);
       //输出访问器属性year的value特性,但是访问器属性并没有value特性,value特性属于数据属性,所以输出undefined
    alert(attribute_two.enumerable);
     //因为访问器属性year并不是在对象上直接定义的属性而是通过defineProperties()方法定义的属性,所以他的Enumerable特性为false,所以输出false;
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2016-08-22 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
JavaScript之对象(一)
数据属性有四个特性。通过特性,可以设置属性。如通过[[Enumerable]]为false就能不让该属性被枚举。另外,为了区别是不是特殊的属性,规范会用两个中括号将特性的名称括起来,如[[Writable]]。
赤蓝紫
2023/03/11
1820
JavaScript之对象(一)
js面向对象思想精要
第一章 原始类型和引用类型 1.原始类型 1.1原始类型(5种) 包括:number,string,boolean,null,undefined; 这是一些简单的数据,保存在栈空间; 1.2.鉴别原始类型 使用typeof方法, eg: console.log(10);//number; 特例:鉴别null时返回的是object; 2.引用类型(js中的对象) 2.1创建 var person = {name:"zhangsan",age:26}; console.log(pers
天天_哥
2018/09/29
1.3K0
十一、详解面向对象
如果要我总结一下学习前端以来我遇到了哪些瓶颈,那么面向对象一定是第一个会想到的。尽管现在对于面向对象有了一些的了解,但是当初那种似懂非懂的痛苦,依然历历在目。
用户6901603
2020/07/23
6060
JS-面向对象的程序设计
今天重读了一下<<JavaScript高级程序设计>>的几章,其中的面向对象的程序设计,写的很好,让自己受益匪浅,特此记录.
拿我格子衫来
2022/01/23
3760
《JavaScript高级程序设计》学习笔记(5)——面向对象编程
 欢迎关注本人的微信公众号“前端小填填”,专注前端技术的基础和项目开发的学习。   本节内容对应《JavaScript高级程序设计》的第六章内容。 1、面向对象(Object-Oriented, OO)的语言有一个标志,那就是它们都有类的概念,而通过类可以创建任意多个具有相同属性和方法的对象。前面提到过,ECMAScript中没有类的概念,因此它的对象也与基于类的语言中的对象有所不同。 ECMA-262把对象定义为:“无序属性的集合,其属性可以包含基本值、对象或者函数。”严格来讲,这就相当于说对象是一组没有
mukekeheart
2018/03/01
7370
javaScript 的面向对象程序
数据属性(数据属性包含一个数据值的位置,这个位置可以读取和写入值,数据属性有4描述)
用户1197315
2019/12/30
1.1K0
Javascript对象
《JavaScript高级程序设计学习笔记》之Javascript对象。 面向对象(Object-Oriented, OO)的语言有一个标志,那就是它们都有类的概念 而通过类可以创建任意多个具有相同属性和方法的对象。 ECMAScript没有类的概念,因此它的对象也与机遇类的语言中的对象有所不同 ES6新增了对象Class的语法糖,这里不讨论ES6
epoos
2022/06/06
4110
javascript 跳跃式前进 (4) - 对象基础理论
ECMAScript中我觉得非常重要的一块就是对于对象的理解了,就我个人而言,我的理解还是不够透彻的; 所以这篇文章不扯多深,只扯扯比较表层的知识;
CRPER
2024/01/26
1100
JavaScript(七)
这一篇,我们说说 ES 中的面向对象。 ECMAScript 中没有类的概念,因此它的对象也与基于类的语言中的对象有所不同。 ECMA-262 把对象定义为: “无序属性的集合,其属性可以包含基本值、对象或者函数。” 对象的每个属性或方法都有一个名字,而每个名字都映射到一个值。我们可以把 ECMAScript 的对象想象成散列表: 一组键值对,其中值可以是数据或函数。
1ess
2021/10/29
3070
js Object.defineProperty()详解
要修改属性的默认特性,就必须使用 Object.defineProperty()方法 ;在了解Object.defineProperty()之前,需要先明白对象属性的一些特性,明白了这些特性之后,对Object.defineProperty()的学习就会顺利很多了。
IT工作者
2022/05/12
2.5K0
深入理解javascript对象
对象被定义为一组属性的无序集合,对象就是一组没有特定顺序的值。对象的每个value值都由一个key来标识,一个key映射一个value值。
javascript艺术
2022/11/22
3910
js程序设计03——面向对象
ECMAScript中有2中属性:数据属性、访问器属性。 数据属性是为了指定某对象的指定key上的一些行为,比如value是否可删除、修改、key可循环遍历等特点。而访问器属性不包含数据值,包含一堆g
用户1141560
2017/12/26
1.2K0
js程序设计03——面向对象
面向对象的程序设计
ECMA-262把对象定义为:”无序属性的集合,其属性可以包含基本值、对象或者函数。”
奋飛
2019/08/15
4430
浅谈JavaScript的面向对象程序设计(一)
  面向对象的语言有一个标志,他们都有类的概念,通过类可以创建多个具有相同属性和方法的对象。但是JavaScript中没有类的概念,因此JavaScript与其他的面向对象语言还是有一定区别的。JavaScript把对象定义为无序属性的集合,其属性可以包含基本值、对象或者函数。对象的每个属性或者方法都有一个名字,而每个名字都映射到一个值。所有我把JavaScript的对象看成一组无序的键值对。 对象是什么   以前曾介绍过对象的创建,建立对象最简单的方式就是建立Object对象的一个实例,再为他添加属性和方
水击三千
2018/02/27
7430
JS面向对象的程序设计
http://www.cnblogs.com/gaojun/p/3386552.html
bear_fish
2018/09/19
1.3K0
浅谈JavaScript 数据属性和访问器属性
创建自定义对象通常有两种方法,第一种就是创建一个Object的实例,然后再为其添加属性和方法,例如:
李才哥
2019/07/10
1.4K0
浅谈JavaScript 数据属性和访问器属性
JavaScript 高级程序设计(第 4 版)- 对象、类与面向对象编程
通过字面量来重写原型时,Person.prototype被设置为等于一个通过对象字面量创建的新对象,此时Person.prototype的constructor属性就不指向Person了
Cellinlab
2023/05/17
6550
JavaScript 高级程序设计(第 4 版)- 对象、类与面向对象编程
关于JavaScript 对象的理解
关于JavaScript 对象的理解 对象 理解对象 ECMA-262把对象定义为:“无序属性的集合,其属性可以包含基本值、对象或者函数。”严格来讲,这就相当于说对象是一组没有特定顺序的值。对象的每个属性或方法都有一个名字,而每个名字都映射到一个值。 我们可以把ECMAScript的对象想象成散列表:无非就是一组名值对,其中的值可以是数据或函数。 每个对象都是基于一个引用类型创建的,即创建自定义对象的最简单方式就是创建一个Object的实例,然后再为它添加属性和方法 合并对象 它 是值 把源对象所有属性 复
程序员海军
2022/02/15
4180
JavaScript原型链与继承
只要是对象,一定有原型对象,就是说只要这个东西是个对象,那么一定有proto属性。(错的)
用户7043603
2022/02/26
1.6K0
《javascript高级程序设计》笔记:对象数据属性和访问器属性
创建自定义对象最简单的方式就是以字面量的形式创建对象(或创建一个Object实例),然后再为它添加属性和方法,如下所示:
全栈程序员站长
2022/07/20
9930
相关推荐
JavaScript之对象(一)
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验