当前位置

网站首页> 程序设计 > 开源项目 > 程序开发 > 浏览文章

JavaScript面向对象的程序设计——“对象的基本概念”的注意要点 - 前端学习笔记

作者:小梦 来源: 网络 时间: 2024-06-23 阅读:

对象的基本概念

面向对象(Object-Oriented,OO),的语言最大的特征就是它们都有类的概念,通过类可以创建任意多个具有相同属性和方法的对象。

创建自定义对象最简单的方式就是创建一个Object 的实例,然后再给他添加属性和方法。如:

var math = new Object();math.π = function pi(){    return Math.PI;};document.write(math.π());

这里借用了Math.PI,最后的结果是无论调用的是math.π还是Math.PI都会返回圆周率的值。其中,前者就是我们自己自定义的对象。又如:

var person = new Object();person.name = "Oliver";person.age = 18;person.job = "Software Engineer";person.sayName = function(){    alert(this.name);};

上面这个对象可以用下面的结构化图像解释清楚:

Object => person    |-name|-age    |-job    |-sayName()|-this.name

这里面person 是对象,又是Object 的实例,其中他有三个属性和一个方法,这个方法用于显示this.name,会被解析为person.name。

上面的例子又可以用字面量的语法写成这样:

var person = {    name: "Oliver",    age: 18,    job: "Software Engineer",    sayName: function(){        alert(this.name);    }};

属性类型

根据ECMA-262 第五版,ECMAScript 中有两种属性(内部值):数据属性和访问器属性。为了表示特性的内部值,该规范把它们放在了两对方括号中,如[[Enumerable]]。

数据属性

数据属性有4 个描述其行为的特性:

  • [[Configurable]]:表示能否通过delete 删除属性;

  • [[Enumerable]]:表示能否通过for-in 循环返回属性;

  • [[Writable]]:表示能否修改属性的值;

  • [[Valu]]:包含这个属性的数据值;

其中,前三个默认都是true,最后一个默认为undefined。

如何修改数据属性默认的特性呢?这就要用到ECMAScript 5 的Object.defineProperty()方法。这个方法接收三个参数:属性所在的对象,属性的名字和一个描述符对象。描述符对象就是上面提到的4 个描述其行为的特性:configurable、enumerable、writable 和value。

修改方式如下:

var person = {};Object.defineProperty(person, "name", {    writable: false,    value: "Oliver"});console.log(person.name); //Oliverperson.name = "Niko";console.log(person.name); //Niko

又如:

var person = {    name: "Troy",    age: 18};Object.defineProperty(person, "name", {    writable: false,    value: "Oliver",    enumerable: false});for (x in person){    console.log(x); //age}

如:

var person = {    name: "Troy",    age: 18};Object.defineProperty(person, "name", {    value: "Oliver",    configurable: false});delete person.name;console.log(person.name) //Oliver

要注意的是,一旦把属性定义为不可配置的,就不能再把它变回可配置的了。

不要在IE8 中使用Object.defineProperty()方法。

访问器属性

该属性不包含数据值,只有一对getter 和setter 函数(两者为可选);4个 特性如下:

  • [[Configurable]]

  • [[Enumerable]]

  • [[Get]]:在读取属性时调用的函数;默认undefined;

  • [[Set]]:在写入属性时调用的函数;默认undefined;

同样,必须使用Object.defindProperty()来定义。如:

var book = {    _year: 2004,    edition: 1};Object.defineProperty(book, "year", {    get: function(){        return this._year;    },    set: function(newValue){        if(newValue > 2004){this._year = newValue;this.edition += newValue - 2004;        }    }});book.year = 2006;console.log(book.edition);

两个默认的属性:_year 和edition。year 前面的下划线是一种常用的记号,用于表示只能通过对象方法访问的属性。

对于上面的下划线不太明白的,可以参考下面一种写法:

var book = {    year: 2004,    edition: 1};Object.defineProperty(book, "setYear", {    get: function(){        return this.year;    },    set: function(newValue){        if(newValue > 2004){this.year = newValue;this.edition += newValue - 2004;        }    }});book.setYear = 2007;console.log(book.edition);console.log(book.year)

两者功能相同,实际上该方法是给book 对象又设置了另一个属性即第一段代码中的_year 和第二段代码中的setYear。

另外,一般在这个方法之前,要创建访问器属性,一般都是使用两个非标准的方法:__defineGetter__()__defineSetter__()。如:

var book = {    name: "hello"};book.__defineGetter__("name",function(){    return "world";});document.write(book.name);

定义多个属性

ECMAScript 5 又定义了一个Object.defineProperties()方法。利用这个方法可以通过描述符一次定义多个属性。如:

var book = {};Object.defineProperties(book, {    _year:{        value: 2004,        writable: true    },    edition:{        value: 1,        writable: true    },    year:{        get: function(){return this._year;        },        set: function(newValue){if(newValue > 2004){    this._year = newValue;        this.edition += newValue - 2004;}        }    }});book.year = 2006;console.log(book.year + " " + book.edition);

还真是奇葩,不知是否浏览器的问题,数据属性还是要加上为true 的writable 访问器属性才能起作用。不是默认为true 么。真是奇怪

读取属性的特征

使用ECMAScript 5 的Object.getOwnPropertyDescriptor()方法,可以取得给定属性的描述符。接收两个参数:所在的对象和要读取其描述符的属性名称。如:

var cars = {};Object.defineProperties(cars, {    name: {        value: "Benz",        writable: false    },    _color: {        value: "White",        writable: true    },    price: {        value: 300000,        writable: true    },    color: {        get: function(){return this._color;        },        set: function(newValue){if(newValue == "Black"){    this._color = "Black";    this.price = 280000}else if(newValue == "White"){    this._color = "White";    this.price = 300000}        }    }});function selectColors(colorValue){    cars.color = colorValue;    document.write(cars.name + ": " + cars.color + "款 " + "(" + cars.price + "元人民币" + ")");}selectColors("Black"); //Benz: Black款 (280000元人民币)selectColors("White"); //Benz: White款 (300000元人民币)var descriptor = Object.getOwnPropertyDescriptor(cars, "name");document.write(descriptor.value + descriptor.writable + descriptor.configurable + descriptor.enumerable); //Benzfalsefalsefalsevar descriptor2 = Object.getOwnPropertyDescriptor(cars, "color");document.write(descriptor2.get + descriptor2.set + descriptor2.configurable + descriptor2.enumerable + descriptor2.value); //function () { return this._color; }function (newValue) { if(newValue == "Black"){ this._color = "Black"; this.price = 280000 }else if(newValue == "White"){ this._color = "White"; this.price = 300000 } }falsefalseundefined

热点阅读

网友最爱