【javascript基础】5、创建对象

原文:【javascript基础】5、创建对象

前言

今天从家里回到了学校,在家呆了十天,胖了几斤的重量,又折腾回学校了,春节回家真是艰辛的路途。随便扯扯我的往返行程:为了省钱我没有选择直飞到长春往返都是到北京转的,这样我和女朋友可以节省4000块左右。1月24号深圳-飞机-北京(飞机晚点1个小时),到北京已经凌晨两点多,机场大巴就剩两个了,做一个大巴到了市里在打的到同学那100块没了,到同学那(天通苑附近)都三点了,吃饭喝酒(一瓶牛栏山+2瓶啤酒)到了五点,睡觉到十点,起床去打了两个小时的篮球,回来没吃饭地铁去车站,差一点没有赶上动车去长春,晚上九点多到了长春,打车去长春理工同学那住,晚上要了肯德基外卖,100块又没了,十二点睡觉三点起床赶车回松原下乡参加同学婚礼,下午1点回来做汽车回家。哎,折腾死人了,放假在家天天叔叔大爷家轮流吃饭,天天打麻将......2月6号四点半起床赶车去市里做火车去长春为了赶上10点25分的车去北京,九点左右到了北京,坐机场块钱去首都机场,坐飞机直飞香港,到香港凌晨3点多,出战坐大巴去深圳湾回深圳,到宿舍8点多。感觉一直都是在赶车,好累,有钱就直飞,哼。

就扯到这,今天和大伙一起学习javascript中的对象和创建对象的一些方式。

对象

javascript中什么是对象呢,javascript中一切都是对象,任何对象的都是基于Object的,确切的说每一个对象都是基于一个引用类型创建的,这个引用类型可以是原生的引用类型也可以是我们自己创建的,这些引用类型是基于Object的。最简单的创建对象的方法是

var person = new Object();
person.name = "hainan";
person.age = "25";

直接new出来一个Object对象,之后给这个对象添加属性和方法。

属性类型

在第五版的javascript中,定义了在内部使用的特性,描述了属性的各种特征,这些特性是javascript引擎使用的,在javascript中我们不能使用它们,为了区别将他们放在了两对方括号中,属性类型分为两种:数据属性和访问器属性。

数据属性

  • [[Configurable]] 表示能否通过delete删除属性,默认为true
  • [[Enumerable]] 表示能否通过for-in枚举属性,默认为true
  • [[Writable]] 表示能否修改属性的值,默认为true
  • [[Value]] 表示这个属性的值,默认为undefined

访问器属性

  • [[Configurable]] 表示能否通过delete删除属性,默认为true
  • [[Enumerable]] 表示能否通过for-in枚举属性,默认为true
  • [[Get]] 读取属性是调用的函数,默认值为undefined
  • [[Set]] 写入属性时调用的函数,默认值为undefined

ECMAScript5中的属性修改时通过Object.defineProperty()这个方法,三个参数分别为对象,属性名,描述符对象。直接看例子,value特性

var person = {};
Object.defineProperty(person,"name",{configurable:true,value:"hainan"})
console.log(person.name);//hainan
//等价于var person = {name : "hainan"}

再看看writable

var person = {};
Object.defineProperty(person,"name",{configurable:true,value:"hainan",writable:false});
person.name = "allenxing";//修改属性
console.log(person.name);//hainan 严格模式下出现错误

下面看看configuration特性

var person = {};
Object.defineProperty(person,"name",{configurable:false,value:"hainan"});
delete person.name;//删除属性
console.log(person.name);//hainan 严格模式下出现错误

configuration属性修改成不可以配置的,就是指为false时,就不能再把它修改成可配置的了,看看例子

var person = {};
Object.defineProperty(person,"name",{configurable:false,value:"hainan"});
Object.defineProperty(person,"name",{configurable:true,value:"hainan"});
//TypeError: Cannot redefine property: name

enumerable特性

var person = {};
Object.defineProperty(person,"name",{configurable:true,value:"hainan"});
for(var pro in person){
  console.log(pro);
}
//不输出
//在chrome下默认的enumeration默认为false
var person = {};
Object.defineProperty(person,"name",{configurable:true,value:"hainan",enumerable:true});
for(var key in person){console.log(key)}
//"name"

再看一下访问器属性

var person = {
  name : "hainan",
  age : 25
}
Object.defineProperty(person,"year",{
   get : function(){
     return this.age + 1;
   },
   set :function(value){
     this.age = value + 10;
   }
});
console.log(person.year);//26
person.year= 10;
console.log(person.age);//20

ECMAScript5还有一个方法Object.defineProperties()可以定义多个属性,用法如下

var person = {}
Object.defineProperties(person,{
   name : {value : "hainan"},
   age : {value : 25},
   year : {
       get :function(){
           return this.age + 1;
       },
       set : function(value){
           this.age = value +10;
      }
   }
});
console.log(person.year);//26
person.year = 10;
console.log(person.age);//25 注意这里

这里我也不知道为啥age的值没有改变,但是下面这样就可以改变了

var person = {name :"hainan",age:25}
Object.defineProperties(person,{
   year : {
       get :function(){
           return this.age + 1;
       },
       set : function(value){
           this.age = value + 10;
      }
   }
});
console.log(person.year);//26
person.year = 10;
console.log(person.age);//20 注意这里

求大神指导下,谢谢

多写@赤脚非大仙的帮助,如果没有指定描述符各属性值,默认是false或者undefined

var person = {}
Object.defineProperties(person,{
   name : {value : "hainan"},
   age : {value : 25,writable : true},
   year : {
       get :function(){
           return this.age + 1;
       },
       set : function(value){
           this.age = value +10;
      }
   }
});
console.log(person.year);//26
person.year = 10;
console.log(person.age);//25 注意这里

其实上面这些修改属性的特性一般的时候我们是用不到的,理解这些可以帮助我们更好的了解javascript的对象。

创建对象

直接new 

创建对象有许多种方法,最简单的就是直接new 一个Object对象,之后再添加属性了

var person = new Object();
person.name  = "hainan";
person.age = 25;

对象字面量

对象字面量是比较常用的创建对象的方法,其实和new差不多,但是写起来比较简洁

var person = {
  name : "hainan",
  age : 25
}

缺点:看起来比较简单,但是假如我们要创建多个对象呢,例如person1,person2.....,直接new和对象字面量都得必须重写代码,也就是会有大量的重复代码。

工厂模式

工厂模式就是解决了代码的不可复用的问题,工厂模式用一个函数封装了创建对象的过程,看代码

function personFactory(name,age){
   var obj = new Object();
   obj.name = name;
   obj.age = age;
   return obj;
}
var person1 = personFactory("hainan",25);
var person2 = personFactory("allenxing",26);

这样我们需要创建一个person对象时只需要使用personFactory()就可以了,解决了创建多个对象的复杂代码问题。其实可以看出本质还是直接new出来一个Object对象,只不过是用函数封装了起来,用一个return返回这个Object对象。

缺点:我们不知道这个对象是具体属于哪个类型的实例,也就是它没有解决对象的识别问题,当然知道对象是Object的实例没有任何实质性意义。

构造函数模式

构造函数可以创建特定类型的对象, Object和Array等是原生的构造函数,是javascript运行时就存在执行环境当中的,不需要我们自己定义构造函数,当我们需要自定义对象时我们可以自定义构造函数,

function Person(name,age){
   this.name = name;
   this.age = age;
}
var person1 = new Person("hainan",25);
var person2 = new Person("allenxing",26);

 这里我们看到了函数的首字母是大写的,这是一种惯例,为了和其它的函数有区别。要想创建Person的实例,必须使用new操作符,看看new都干些什么了

  1. 创建一个新的对象
  2. 将构造函数的作用域赋值给这个对象,也就是this指向了这个新对象
  3. 执行构造函数中的代码
  4. 返回这个新对象

person1和person2是Person对象的不同实例,它们有一个相同的constructor属性,并且它们都是Person的实例

console.log(person1.constructor == Person);//true
console.log(person2.constructor == Person);//true
console.log(person1 instanceof Person);//true
console.log(person2 instanceof Person);//true

构造函数模式解决了对象识别的问题。

我们知道构造函数也是函数,如果不使用new关键字,那么会是怎样的呢,我们知道在全局作用域中this指向的是window,那么直接使用构造函数应该就是将属性或方法添加到了window上了,我们看看是不是这样的情况

function Person(name,age){
   this.name = name;
   this.age = age;
}
var person = Person("hainan",25);//添加到了window上
console.log(window.name);//hainan

没有new实例时,构造函数就普通函数,添加到了this指向的对象中了,在这里this指向的是window。

缺点:每当new一个实例出来,每个实例都要重新创建对象的函数,每个实例中的函数是不同的,因为函数也是对象,定义一个函数也就是实例化一个对象。

function Person(name,age){
   this.name = name;
   this.age = age;
   this.getName = function(){return this.name};//等于this.getName = new Function("return this.name");
}
var person1 = new Person("hainan",25);
var person2 = new Person("allenxing",26);
console.log(person1.getName == person2.getName);//false

虽然这个函数是所以实例共享的,但是每个实例中都是一个副本,显然这对性能是不利的。当然我们可以这样干

function Person(name,age){
   this.name = name;
   this.age = age;
   this.getName = getName;
}
function getName(){return this.name;}
var person1 = new Person("hainan",25);
var person2 = new Person("allenxing",26);
console.log(person1.getName == person2.getName);//true

这样就是每个实例都引用了同一个函数,所以是相等的,但是如果方法很多,我们不能把所有的函数就定义在全局作用域当中,这就需要其他的模式来解决了。

原型模式

原型和原型链我们之前已经讨论过了,这里我们直接学习这个原型模式就好了。

function Person(){}
Person.prototype = {
  constructor : Person,
  name : "hainan",
  getName : function(){return this.name}
}
var person1 = new Person();
var person2 = new Person();
console.log(person1.getName == person2.getName);//true

这样,原型模式解决了构造函数中的每个实例都有一个方法的副本的性能和内存问题,但是原型模式也有自己的不足

缺点:原型中的属性是共享的,这是他的优点也是他的缺点,当属性是引用类型的时候,这个问题就体现出来了。

function Person(){}
Person.prototype = {
  constructor : Person,
  name : "hainan",
  friends : ["James"],
  getName : function(){return this.name}
}
var person1 = new Person();
person1.friends.push("Melo");
var person2 = new Person();
console.log(person2.friends);//"James", "Melo"

可以看到我们给person1添加一个朋友,结果person2的朋友也添加上了,就是由于所有实例共享原型中的属性。

组合模式(构造函数和原型模式)

这种是最常用的方式也是大家推荐的方式,构造函数用于定义实例属性,原型模式用于定于方法和共享的属性,这样就会结合两种模式的优点,每个实例都会有一个实力属性的副本,同时共享着对方法的引用,节省了内存。

function Person(name,age){
  this.name = name;
  this.age = age;
  this.friends = ["James"];
}
Person.prototype = {
  constructor : Person,
  getName : function(){return this.name}
}
var person1 = new Person("hainan",25);
person1.friends.push("Melo");
console.log(person2.friends);//"James", "Melo"
var person2 = new Person("allenxing",26);
console.log(person2.friends);//"James"

动态原型模式

所谓的动态原型模式就是将原型模式和构造模式放在了构造函数中,在定义方法时先检查是否存在这个方法,如果存在就什么就不做,若果不存在就在原型上添加这个方法。

function Person(name,age){
  this.name = name;
  this.age = age;
  if(typeof this.getName != "function"){
    Person.prototype.getName = function(){
      return this.name;
    }
  }
}
var person1 = new Person("hainan",25);
var person2 = new Person("allenxing",26);

寄生构造函数模式

书上说前面的几种不合适的话就可以使用这种模式,这个模式和工厂模式其实很类似,都是将创建对象的过程封装到一个函数内部,只不过这种模式最后使用了new操作符,new操作符我们以后在详细说说,这里就不说了。

function Person(name,age){
   var obj = new Object();
   obj.name = name;
   obj.age = age;
   return obj;
}
var person1 = new Person("hainan",25);
var person2 = new Person("allenxing",26);

这里是使用了带返回值的构造函数,带的返回值会覆盖构造函数默认的返回值,这个我会写一个关于这个的文章。

稳妥构造函数模式

书上说的稳妥对象就是没有公共属性,其方法也不引用this对象,看看例子,这个大家还是看看《高级程序设计》上的吧,和前面的几种对比一下就知道为啥叫稳妥了,

function Person(name,age){
  var obj = new Object();
  obj.getName = function(){
    return name;//没有使用this
  };
  return obj;
}
var person1  = Person("hainan",25);//没有使用new
console.log(person1.getName());

小结

这篇就这样吧,开学了,还是得先紧起来,好好写博客,抓紧搞论文。大家对这篇有什么疑问尽量说,对我这篇有什么意见尽量提,小弟谢谢大家了。下篇说说继承。

时间: 2024-10-10 01:17:41

【javascript基础】5、创建对象的相关文章

JavaScript基础函数整理汇总_基础知识

这里给大家整理汇总了一些javascript的基础函数,都是比较常用和实用的.整理出来也有助于大家更好的理解javascript. 复制代码 代码如下: <script type="text/javascript">     /*创建函数和字面量函数*/     /*         function add(){             alert("函数创建成功")         };         var testfunction=functi

【javascript基础】7、继承

原文:[javascript基础]7.继承 前言 由于本人水平有限,所以有些高手觉得现在写的内容偏容易,要一点点来嘛,今天和大家学习或者复习一下javascript的继承.我也就是尽量写吧······ 继承 javascript的继承其实主要就是通过原型链来实现的,原型链我们之前已经和大家一起学习过,这里就不浪费大家的时间了.javascript连类都没有,还说啥继承呢,这还是模拟类的继承.<javascript高级程序设计>上分成了几个方式,有的书上分为类式继承,原型式继承,这就是模拟其他语

javascript基础知识分享之类与函数化_基础知识

1.对象适合于收集和管理数据,容易形成树型结构. Javascript包括一个原型链特性,允许对象继承另一对象的属性.正确的使用它能减少对象的初始化时间和内存消耗. 2.函数它们是javascript的基础模块单元,用于代码复用.信息隐藏和组合调用.函数用于指定对象的行为.一般来说,编程就是将一组需求分解成一组函数和数据结构的技能. 3.模块我们可以使用函数和闭包来构造模块.模块是一个提供接口却隐藏实现状态和实现的函数或对象. 1.自定义类型--构造函数模式(伪类模式) 在基于类的系统中,对象是

JavaScript基础知识点归纳(推荐)_基础知识

定义在函数外的变量一定是全局变量:定义在函数内的变量,如果声明了var,那该变量就是局部变量,如果不声明var,那么该变量就是全局变量. 1.全局变量与局部变量 JavaScript var global = "Global"; test(); function test(){ var local = "Local"; document.writeln(global); document.writeln(local); } document.writeln(glob

JavaScript基础篇(3)之Object、Function等引用类型_javascript技巧

阅读目录 Object类型 1.通过构造函数来创建 2.通过字面量表示法来创建对象 Array类型 同样Array也有两种创建方式: 如果我们想要打印数组中所有的值,直接打印数组的变量名就可以: 往数组添值: 栈方法.队列方法:  关于数组的排序:  数组的一些操作方法: 查找位置方法 迭代方法 归并方法 Date类型 RegExp类型 Function类型 三种表示法: 方法重载 函数内部属性(arguments 和 this) 基本包装类型 浏览器的内置对象 URI 编码方法 总结 我们在<

前端技术系列课程(No.2) &amp;#8211; HTML/CSS/JavaScript基础

本次课为系列课程的第二课,由舒克带来的"HTML/CSS/JavaScript"基础知识,课程中着重介绍了HTML的语义化,因为语义化是前端工程师最容易理解又最难掌握的,比如何时使用什么样的标签,这取决于前端工程师对标签和页面内容的理解.要注意频道首页和详情页是不同的,频道首页中的信息比较琐碎,详情页中的内容更像"文章",因此内容的语义是有差别的.这一点需要注意. http://www.slideshare.net/lijing00333/htmlcssjs 在HT

【javascript基础】3、变量和作用域

原文:[javascript基础]3.变量和作用域 前言 这篇和大家说一下javascript中的变量和作用域,由于是将基础嘛,主要给大家捋一下知识,不想翻开书复习的道友可以看一下,打算刚开始学习javascript的同学可以扫一眼. PS:jQuery源码交流群( 239147101)等你来,群里高手云集,让我受益匪浅,尽量少灌水. 变量 javascript中有两种变量,分别是基本类型和引用类型,基本类型是Null,Undefined,String,Boolean,Number这五种,前面简

JavaScript 基础篇(一)_基础知识

JavaScript 基础篇(一) 基础篇 Javascript:一.数据类型和值 javascript:允许使用3种基本类型数据--------数字.字符串.布尔值,此外还支持两种小数据类型null(空)和undefine(未定义). javascript:还支持符合数据类型-对象(object),javascript中对象分两种,一种对象表示的已命名的值的无序集合,另一种表示有 编号的值的有序集合.其实有序集合就是数组(Array). javascript:还定义了另一种特殊对象----函数

extjs4-关于 Extjs 4.X中 Ext.Function源码中的一些问题, 关于javascript基础知识的

问题描述 关于 Extjs 4.X中 Ext.Function源码中的一些问题, 关于javascript基础知识的 Ext.Function中定义了如下一个叫做flexSetter的函数,其作用看看就明白 问题在于 其中做a===null判断的地方为什么不用a==null呢? 源码如下: Ext.Function = { /** * A very commonly used method throughout the framework. It acts as a wrapper around