【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());

小结

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

【javascript基础】5、创建对象,布布扣,bubuko.com

时间: 2024-12-14 13:11:31

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

JavaScript基础之创建对象的方法

ECMA-262把对象定义为:"无序属性的集合,其属性可以包含基本值.对象或者函数."严格来讲,这就相当于说对象是一组没有特定顺序的值.对象的每个属性或者方法都有一个名字,而每个名字都映射到一个值.正因为这样,我们可以把ECMAScript的对象想像成散列表:无非就是一组名值对,其中值可以是数据或函数. 创建对象的方式多种多样,理解和掌握每种创建对象的方法对于学会JavaScript这门语言是十分重要的. 一.使用Object构造函数 var person = new Object()

Javascript基础篇小结

Javascript基础篇小结 字数9973 阅读3975 评论7 喜欢28 转载请声明出处 博客原文 随手翻阅以前的学习笔记,顺便整理一下放在这里,方便自己复习,也希望你有也有帮助吧 第一课时 入门基础 知识点: 操作系统就是个应用程序 只要是应用程序都要占用物理内存 浏览器本身也是一个应用程序 浏览器本身只懂得解析HTML 调用浏览器这个应用程序的一个功能绘制 1.javascript介绍 JavaScript操作DOM的本质是=获取+触发+改变 目的:就是用来操作内存中的DOM节点 修改D

JavaScript基础细讲

JavaScript基础细讲 JavaScript语言的前身叫作Livescript.自从Sun公司推出著名的Java语言之后,Netscape公司引进了Sun公司有关Java的程序概念,将自己原有的Livescript 重新进行设计,并改名为JavaScript. JavaScript是一种基于对象和事件驱动并具有安全性能的脚本语言,有了JavaScript,可使网页变得生动.使用它的目的是与HTML超文本标识语言.Java 脚本语言一起实现在一个网页中链接多个对象,与网络客户交互作用,从而可

JAVASCRIPT基础05-对象

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <ti

一步步学习javascript基础篇(3):Object、Function等引用类型

我们在<一步步学习javascript基础篇(1):基本概念>中简单的介绍了五种基本数据类型Undefined.Null.Boolean.Number和String.今天我们主要介绍下复杂数据类型(即引用数据类型) Object类型 我们用的最多的引用类型就属object类型了,一般用来存储和传输数据是再好不过的.然,它的两种创建方式我们是否了解呢? 1.通过构造函数来创建 如: var obj = new Object(); 在js中的引用类型有个非常灵活的用法,可以动态的附加属性和赋值.

【javascript基础】7、继承

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

【javascript基础】6、new与构造函数

原文:[javascript基础]6.new与构造函数 前言 上篇说创建对象的时候提到了带返回值的构造函数,那里没有和大家说这个问题,今天就和大家一起学习构造函数和new操作符.我也是最近才稍微弄明白点这个构造函数,以前总是忽略一些问题,现在就是想到哪块不行,就研究下,查查资料,自己捣鼓捣鼓,希望大家也随手记一下自己突然想起的哪块不熟悉知识点. javascript中的类 JavaScript 是面向对象的语言,但是他的面向对象不是基于类的,是基于原型的.javascript中没有是类,任何所谓

JavaScript基础--面向对象三大特性(八):继承封装多态

一.构造函数基本用法:function 类名(参数列表){属性=参数值} 1 function Person(name,age){ 2 this.name = name; 3 this.age = age; 4 } 5 6 //创建Person对象的时候,可以直接给名字和年龄 7 var p1 = new Person('abc',80); 8 window.alert(p1.name); 9 var p2 = new Person('hello',9); 10 window.alert(p2.

JavaScript 基础回顾——对象

JavaScript是基于对象的解释性语言,全部数据都是对象.在 JavaScript 中并没有 class 的概念,但是可以通过对象和类的模拟来实现面向对象编程. 1.对象 在JavaScript中,对象被定义为无序属性的集合,属性可以是任何类型的值,包括其他对象或函数.函数作为属性值时称为“方法”,即对象的行为. (1)对象常用的内部属性 对象的内部属性是由JavaScript 规范定义的,由运行代码的系统来访问.对象常用的内部属性: prototype        对象        获