在js 中创建最简单的对象,然后给它添加属性或者方法 示例如下:

    var obj = new Object();
//或者
var obj = {};
obj.name = '张三';
obj.fun = function(){};

上创建的对象 中有 name 属性和一个 fun 方法,也可如下创建

    var obj = {
name: '张三',
fun: function(){}
}

这个例子中的 obj 对象与前面例子中的 obj 对象是一样的,都有相同的属性和方法。这些 属性在创建时都带有一些特征值(characteristic),JavaScript 通过这些特征值来定义它们的行为。

1. 属性类型

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

(1). 数据属性

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

Configurable   // 表示能否通过 delete 删除属性从而重新定义属性
Enumerable // 表示能否通过 for-in 循环及枚举返回属性
Writable // 表示能否修改属性的值
Value // 表示这个属性的数据值,这个特性的默认值为 undefined。

对于像前面例子中那样直接在对象上定义的属性,它们的 Configurable 、Enumerable 和 Writable 特性都被设置为 true,而 Value 特性被设置为指定的值。

要修改属性默认的特性,必须使用 ECMAScript 5 的 Object.defineProperty()方法。这个方法 接收三个参数:属性所在的对象、属性的名字和一个描述符对象。其中,描述符(descriptor)对象的属 性必须是:configurable、enumerable、writable 和 value。设置其中的一或多个值,可以修改 对应的特性值。 如下

    var p = {};
Object.defineProperty(p,"name",{
configurable: true,
writable: true,
enumerable: true,
value: ""
})
configurable 属性
    var p = {};
Object.defineProperty(p,"name",{
configurable: false, //如果不写该属性或者值为false delete 删除不会生效,在严格模式下会报错
value: ""
})
delete p.name
console.log(p); //{p:'123'}

一旦把属性定义为不可配置的, 就不能再把它变回可配置了。此时,再调用 Object.defineProperty()方法修改除 writable 之外 的特性,都会导致错误:

        var p = {};
Object.defineProperty(p,"name",{
configurable: false,
value: ""
})
Object.defineProperty(p,"name",{
configurable: true,
value: ""
})
//跑出错误

也就是说,可以多次调用 Object.defineProperty()方法修改同一个属性,但在把 configurable 特性设置为 false 之后就会有限制了

writable 属性


        var p = {};
Object.defineProperty(p,"name",{
writable: false, // 不写该属性 或者值为false 时不能修改值
enumerable: true,
value: ""
})
p.name = ;
console.log(p); //{p:'123'}
enumerable 属性
        var p = {};
Object.defineProperty(p,"name",{
enumerable: true, // 不写该属性 或者值为false 时不能遍历得到对象属性值
value: ""
})
for(var i in p){
console.log(p[i]); //未获得值
}

在调用 Object.defineProperty()方法时,如果不指定,configurable、enumerable 和 writable 特性的默认值都是 false。多数情况下,可能都没有必要利用 Object.defineProperty() 方法提供的这些高级功能。不过,理解这些概念对理解 JavaScript 对象却非常有用。

(2). 访问器属性

    访问器属性不包含数据值;它们包含一对儿 getter 和 setter 函数(不过,这两个函数都不是必需的)。 在读取访问器属性时,会调用 getter 函数,这个函数负责返回有效的值;在写入访问器属性时,会调用 setter 函数并传入新值,这个函数负责决定如何处理数据。访问器属性有如下 4 个特性。

configurable    // 表示能否通过 delete 删除属性从而重新定义属性
Enumerable // 表示能否通过 for-in 循环返回属性
Get // 在读取属性时调用的函数。默认值为 undefined。
Set // 在写入属性时调用的函数。默认值为 undefined。
configurable,Enumerable同数据属性一样的。
        var p = {
_year: ,
num :
};
Object.defineProperty(p,"year",{
get: function(){
return this._year;
},
set: function(newValue){
if(newValue > ){
this._year = newValue;
this.num += newValue - ;
}
}
})
p.year = ;
console.log(p.num); //

以上代码创建了一个 p 对象,并给它定义两个默认的属性: _year 和 num。_year 前面 的下划线是一种常用的记号,用于表示只能通过对象方法访问的属性。而访问器属性 year 则包含一个 getter 函数和一个 setter 函数。getter 函数返回_year 的值,setter 函数通过计算来确定正确的版本。因此, 把 year 属性修改为 2001 会导致_year 变成 2001,而 num 变为 2。这是使用访问器属性的常见方 式,即设置一个属性的值会导致其他属性发生变化。

不一定非要同时指定 getter 和 setter。只指定 getter 意味着属性是不能写,尝试写入属性会被忽略。 在严格模式下,尝试写入只指定了 getter 函数的属性会抛出错误。类似地,只指定 setter 函数的属性也 不能读,否则在非严格模式下会返回 undefined,而在严格模式下会抛出错误。

支持 ECMAScript 5 的这个方法的浏览器有 IE9+(IE8 只是部分实现)、Firefox 4+、Safari 5+、Opera 12+和 Chrome。在这个方法之前,要创建访问器属性,一般都使用两个非标准的方法: __defineGetter__()和__defineSetter__()。这两个方法最初是由 Firefox 引入的,后来 Safari 3、 Chrome 1 和 Opera 9.5 也给出了相同的实现。使用这两个遗留的方法,可以像下面这样重写前面的例子。

var p = {
_year: ,
  num:
};
//定义访问器的旧有方法
p.__defineGetter__("year", function(){
return this._year;
});
p.__defineSetter__("year", function(newValue){
if (newValue > ) {
this._year = newValue;
this.num += newValue - ;
}
});
p.year = ;
alert(p.num); //

在 不 支 持 Object.defineProperty() 方 法 的 浏 览 器 中 不 能 修 改  Configurable  和 Enumerable 。

2. 定义属性
  Object.defineProperty()
//方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性, 并返回这个对象。
        var p = {};
Object.defineProperty(p,"name",{
enumerable: true,
value: ""
})
  
  
Object.defineProperties() //方法直接在一个对象上定义新的属性或修改现有属性,并返回该对象。可以定义哥多个属性
  
var p = {};
Object.defineProperties(p, {
name: {
value: true,
writable: true
},
name2: {
value: 'Hello',
writable: false
}
});

3 读取属性的特性

  使用 ECMAScript 5 的 Object.getOwnPropertyDescriptor()方法,可以取得给定属性的描述 符。这个方法接收两个参数:属性所在的对象和要读取其描述符的属性名称。返回值是一个对象,如果 是访问器属性,这个对象的属性有 configurable、enumerable、get 和 set;如果是数据属性,这 个对象的属性有 configurable、enumerable、writable 和 value.

     var p = {
num :
};
Object.defineProperties(p,{
_year: {
value :
},
year:{
get: function(){
return this._year;
},
set: function(newValue){
if (newValue > ) {
this._year = newValue;
this.num += newValue - ;
}
}
}
})
var obj = Object.getOwnPropertyDescriptor(p,'_year');
console.log(obj.value); //
console.log(obj.configurable); //false
console.log(typeof obj.get); //undefined var obj1 = Object.getOwnPropertyDescriptor(p, "year");
console.log(obj1.value); //
console.log(obj1.enumerable); //false
console.log(typeof obj1.get); //"function"

对于数据属性_year,value 等于最初的值,configurable 是 false,而 get 等于 undefined。 对于访问器属性 year,value 等于 undefined,enumerable 是 false,而 get 是一个指向 getter 函数的指针。

在 JavaScript 中,可以针对任何对象——包括 DOM 和 BOM 对象,使用 Object.getOwnPropertyDescriptor()方法。

 4.创建对象

4.1 工厂模式

            function person(name, sex, age){
var obj = new Object();
obj.name = name;
obj.sex = sex;
obj.age = age;
obj.sayName = function(){
console.log(this.name);
}
return obj;
}
var zs = person('zs','M',);
var ls = person('ls','F',);

函数 person()能够根据接受的参数来构建一个包含所有必要信息的 对象。可以无 数次地调用这个函数,而每次它都会返回一个包含三个属性一个方法的对象。工厂模式虽然解决了创建 多个相似对象的问题,但却没有解决对象识别的问题

4.2构造函数模式

            function Person(name, sex, age){
this.name = name;
this.sex = sex;
this.age = age;
this.sayName = function(){
console.log(this.name);
}
}
var zs = new Person('zs','M',);
       var ls = new Person('ls','M',);
       console.log(zs.constructor === Person);//true

Person()中的代码 除了与 person()中相同的部分外,还存在以下不同之处:

  没有显式地创建对象;   

  直接将属性和方法赋给了 this 对象;   

  没有 return 语句。

要创建 Person 的新实例,必须使用 new 操作符。以这种方式调用构造函数实际上会经历以下 4 个步骤:

  (1) 创建一个新对象;
  (2) 将构造函数的作用域赋给新对象(因此 this 就指向了这个新对象);
  (3) 执行构造函数中的代码(为这个新对象添加属性);
  (4) 返回新对象。
  在前面例子的最后,zs 保存着 Person 的一个的实例。这个对象有一个 constructor(构造函数)属性,该属性指向 Person,如下所示。

  console.log(zs.constructor === Person);//true

  1. 将构造函数当作函数

    构造函数与其他函数的唯一区别,就在于调用它们的方式不同。不过,构造函数毕竟也是函数,不 存在定义构造函数的特殊语法。任何函数,只要通过 new 操作符来调用,那它就可以作为构造函数;而 任何函数,如果不通过 new 操作符来调用,那它跟普通函数也不会有什么两样。例如,前面例子中定义 的 Person()函数可以通过下列任何一种方式来调用。

// 当作构造函数使用
var person = new Person("Nicholas", "M", 21); person.sayName(); //"Nicholas"
// 作为普通函数调用
Person("Greg", "M", ); // 添加到window window.sayName(); //"Greg"
// 在另一个对象的作用域中调用
var o = new Object();
Person.call(o, "Kristen", , "Nurse"); o.sayName(); //"Kristen"

2. 构造函数的问题

  构造函数模式虽然好用,但也并非没有缺点。使用构造函数的主要问题,就是每个方法都要在每个实例上重新创建一遍,zs 和 ls 都有一个名为 sayName()的方法,但那 两个方法不是同一个 Function 的实例.

this.sayName = new Function("console.log(this.name)"); // 与声明函数在逻辑上是等价的

  以这种方式创建函数,会导致不同的作用域链和标识符解析,但 创建 Function 新实例的机制仍然是相同的。因此,不同实例上的同名函数是不相等的.  

console.log(person1.sayName == person2.sayName); //false

  创建两个完成同样任务的 Function 实例的确没有必要;况且有 this 对象在,根本不用在 执行代码前就把函数绑定到特定对象上面。因此,大可像下面这样,通过把函数定义转移到构造函数外 部来解决这个问题。

    function Person(name, sex, age){
this.name = name;
this.sex = sex;
this.age = age;
this.sayName = sayName;
}
function sayName(){
console.log(this.name);
}
var zs = new Person('zs','M',);
var ls = new Person('ls','M',);
console.log( zs.sayName == ls.sayName ); //true

在这个例子中,我们把 sayName()函数的定义转移到了构造函数外部。而在构造函数内部,我们 将 sayName 属性设置成等于全局的 sayName 函数。这样一来,由于 sayName 包含的是一个指向函数 的指针,因此 zs 和 ls 对象就共享了在全局作用域中定义的同一个 sayName()函数。


 

对象 Object的更多相关文章

  1. 一个简单的游戏开发框架(五.对象Object)

    前面提到我们把行为Action从对象Object中分离了出来,用各种不同的行为组合出对象的功能.大家都知道,面向对象的一个类,就是数据和操作的集合.操作(行为)被分离出来了,数据怎么办呢?操作依赖的数 ...

  2. Java中的对象Object方法之---wait()和notifiy()

    这一篇咋们继续,接着来介绍wait()和notify()方法,我们都知道这两个方法和之前介绍的方法不太一样,那就是这两个方法是对象Object上的,不属于Thread类上的.我们也知道这两个方法是实现 ...

  3. js内置对象-Object

    1)Object构造函数的方法 返回指定对象的原型对象 Object.getPrototypeOf(mymap); /*{featureStyle: {…}, selfLayersCount: nul ...

  4. 对象Object

    功能分类                       1. 创建对象 把各对数自身拥有的可枚举属性复制到第一个对象并返回:obj = Object.assign(o1, o2, o3),o1=obj ...

  5. java的类class 和对象object

    java 语言的源代码是以类为单位存放在文件中,已public修饰的类名须和存放这个类的源文件名一样.而 一个源文件中只能有一个public的类,类名的首字母通常为大写. 使用public修饰的类可以 ...

  6. 1月5日 对象Object, 含过去看的英文档的总结链接

    Object 也是一种数据类型,可以有属性,有method. 反之,在Ruby中,每一种数据类型都是Object.如String,Integer,Float,Array,Hash. IN Ruby e ...

  7. vue props 传入对象Object,如果外层更改属性,默认里面是不更新,需要使用 this.$set(this.datese1, 'xsfaDateYear1', '')

    vue props 传入对象Object,如果外层更改属性,默认里面是不更新,需要使用 this.$set(this.datese1, 'xsfaDateYear1', '')

  8. Java常见对象Object类中的个别方法

    Java常见对象Object类 public int hashCode() : 返回该对象的哈希码值. 注意:哈希值是根据哈希算法计算出来的一个值,这个值和地址值有关,但是不是实际地址值.你可以理解成 ...

  9. Java - 对象(object) 具体解释

    对象(object) 具体解释 本文地址: http://blog.csdn.net/caroline_wendy/article/details/24059545 对象(object)的实例能够是 ...

  10. JS json对象(Object)和字符串(String)互转方法

    [JS json对象(Object)和字符串(String)互转方法] 参考:https://blog.csdn.net/wenqianla2550/article/details/78232706 ...

随机推荐

  1. python3 urllib模块使用

    urllib模块使用 urllib.request urllib.request.urlopen(url, data=None, [timeout, ]*, cafile=None, capath=N ...

  2. [UE4]非常实用的插值Lerp

    Alpha的数值范围是0到1. if(Alpha==0) ReturnValue=A if(Alpha==1) ReturnValue=B 如果Alpha在0到1之间,Alpha值越接近0则ReVal ...

  3. Authentication required (packagist.phpcomposer.com) 账号密码到哪里获取?

    安装好composer后,执行composer install 报这个错 面对这个错有两种方法.1,他说你的composr 版本不够稳定,composer update 一下,或者 composer ...

  4. php安装imagemagick扩展 常见问题与解决方案(win平台)

    1.写在前面 1-1.ImageMagick介绍 ImageMagick是一套功能强大.稳定而且开源的工具集和开发包,可以用来读.写和处理超过89种基本格式的图片文件,包括流行的TIFF.JPEG.G ...

  5. centos 7 修改host文件

    centos7与之前的版本都不一样,修改主机名在/ect/hostname 和/ect/hosts 这两个文件控制 首先修改/etc/hostname vi /etc/hostname 打开之后的内容 ...

  6. PHP微信公众号开发之自动回复

    先把源码类发出来 <?php /** 自己封装 微信 开发api */ header('Content-type: text/html; charset=utf-8');#设置头信息 class ...

  7. IDEA Git 配置及使用

    1.下载并安装 Git 2.新建项目 3.配置版本控制器 4.新建github仓库 5.定位到项目根目录,执行命令 创建git仓库时忘记添加 .gitignore 怎么办? vi .gitignore ...

  8. 基于拖放布局的 Twitter Bootstrap 网站生成器

    简单的几个拖放操作就能做出漂亮的 Twitter Bootstrap 网站?是的,LayoutIt 是一个 Twitter Bootstrap 界面生成器,能够帮助你快速制作出网站和界面模型,同时能够 ...

  9. Android 支付密码输入框,自定义EditText实现密码输入框功能;

    刚撸出来的密码输入框,注释和逻辑看着挺清晰的,一些属性还没有添加,下个博客把属性添加上去: 看一下图: 直接看代码吧! import android.content.Context; import a ...

  10. 面向对象之—property,staticmethod

    一 特性( property) property是一种特殊的属性,访问它时会执行一段功能(函数)然后返回值. property是内置的一种封装方法:把一个属性“伪装”成一个数据属性,做法就是在需要伪装 ...