js中对象与对象创建方法的各种方法

 更新时间:2019年02月27日 11:31:44   作者:Yellow_ice  
这篇文章主要给大家介绍了关于js中对象与对象创建方法的各种方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧

前言

不管是哪门语言,千变万化不离其宗,深入理解其本质,方能应用自如。对应到js,闭包,原型,函数,对象等是需要花费大功夫思考、理解的。

这一次我们来说一说在JavaScript中经常会用到的一个复杂基本类型,对象,先从对象的属性讲起,再讲对象的创建方法,基本涵盖了创建对象的各种方法,大家一起学习呀~

一、对象

要掌握对象的使用及继承,首先当然需要先理解它,接下来,将会对对象的属性类型进行一个整理

    1、什么是对象

    对象其实是无序属性的集合,其属性可以包含基本值,对象或者函数,比如像下面这个例子就是一个person对象啦

var person = {
 name: "NIcholas",
 age: 29,
 sayName: function() {
 console.log(this.name);
 }
}

    从上面的例子我们可以看到,对象可以是由属性和其相应的值构成,对象中可以包含函数,也可以包含其它对象

    2、属性类型

    在JavaScript中,其实有两种属性,包括数据属性和访问器属性

    (1)数据属性

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

    a、[[Configurable]]:表示能否通过delete删除属性从而重新定义属性,默认值为true

    b、[[Enumerable]]:表示能否通过for-in循环返回属性,默认值为true

    c、[[Writable]]:表示能否修改属性的值,默认值为true

    d、[[Value]]:包含这个属性的数据值,默认值为undefined

    一般来说,数据属性都有自己的默认值,那么如果我们要修改数据属性默认的特性,应该怎么办呢?这个时候就需要用到Object,defineProperty()方法啦,这个方法接收三个参数:属性所在的对象,属性的名字和一个描述对象,来看下面的例子

var person = {};
Object.defineProperty(person, "name", {
 writable: false,
 value: "Nicholas"
});

console.log(person.name); // Nicholas
// 重新赋值
person.name = "Greg";
console.log(person.name); // Nicholas

    从上面的例子我们可以看到,因为设置了person对象的name属性为不可修改,因此无论你在后面怎么修改person的name属性的值,name属性的值都不会发生改变

    (2)访问器属性

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

    a、[[Configurable]]:表示能否通过delete删除属性从而重新定义属性,默认值为true

    b、[[Enumerable]]:表示能否通过for-in循环返回属性,默认值为true

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

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

    访问器属性不能直接定义,必须调用Object.definedProperty()来定义的,来看下面的例子

var book = {
 _year:2004,
 edition:1
}

Object.defineProperty(book, "year", {
 get: function() {
 return this._year;
 },
 set: function(newValue) {
 this._year = newValue;
 }
});

    这里要说明一下,book对象中_year前面的下划线是一种常用的记号,用于表示只能通过对象方法访问的属性,还有呀,大家不要小看了Object.definedProperty()这个方法,这个方法可是很强大呀,像vue的双向数据绑定,其实就是用到了这个方法去实现的

    (3)读取属性的特性

    既然JavaScript有数据属性和访问器属性,那么我们怎样才能读取它们呀,这个时候就需要用到Object.getOwnPropertyDescriptor()方法了,这个方法可以取得给定属性的描述符,接收两个参数,分别是属性所在的对象和要读取其描述符的属性名称

二、对象的创建

    在了解了对象之后,接下来我们就需要说下怎么创建对象了,最简单的方法,当然就是使用前面说的对象字面量的方法去创建啦,但是如果我们需要创建好多个对象,用前面的方法就不行了,我们需要用到其它更加简便的方法,帮助我们创建出多个对象

    1、工厂模式

    这种模式其实是一个设计模式,抽象了创建具体对象的过程,主要是通过在函数内部创建一个对象,为其添加属性和方法,并将对象返回,从而实现创建多个对象的目的,来看下面的例子

function createPerson(name, age) {
 var o = new Object();
 o.name = name;
 o.age = age;
 o.sayName = function() {
  console.log(this.name);
 };
 return o;
}

var person1 = createPerson("Nicholas", 29);
var person2 = createPerson("Greg", 27);

    优点:能够解决创建多个对象的问题,兼容各个浏览器

    缺点:没有解决对象识别的问题,不能知道一个对象的类型

    2、构造函数模式

    这种模式主要通过创建自定义的构造函数,从而定义自定义对象类型的属性和方法,来看下面例子

function Person(name, age) {
 this.name = name;
 this.age = age;
 this.sayName = function() {
  console.log(this.name);
 }
}

var person1 = new Person("Nicholas", 29);
var person2 = new Person("Greg", 27);

    这里要说明一下,构造函数需要以一个大写字母开头,而非构造函数应该以一个小写字母开头,这个主要是为了区别构造函数和其它函数,构造函数其实本身也是函数,只是用来创建对象而已

    其中,要创建Person的新实例,需要使用new操作符,其实这里会经过4个步骤,首先,将会创建一个新对象,接着会将构造函数的作用域赋给新对象,this指向了这个对象,接着会执行构造函数中的代码,为这个新对象添加属性,最后会返回新对象

    优点:可以创建多个对象,解决对象的识别问题

    缺点:每个实例都会创建不同的function实例,而其实创建完成同样任务的function实例是很没有必要的

    这里还是要说明一下,对象类型的检测需要用到instanceof操作符,比如像上面的例子可以用下面的方法检测

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

    使用构造函数模式可以解决对象的识别问题,而这也是工厂模式无法办到的

    3、原型模式

    我们都知道,每个函数都有一个prototype属性,这个属性是一个指针,指向一个对象,而这个对象就是原型对象,包含了所有实例共享的属性和方法,如果我们要创建的对象需要共享属性和方法,就可以使用这种方法创建

function Person() {
}

Person.prototype.name = "Nicholas";
Person.prototype.age = 29;
Person.prototype.sayName = function() {
 console.log(this.name);
}

var person1 = new Person();
var person2 = new Person();
person1.sayName(); // Nicholas
person2.sayName(); // Nicholas

    优点:不用为构造函数传递参数,可以创建多个相同的对象

    缺点:原型中的属性被很多实例共享,当属性为包含引用类型值的属性时,修改一个实例中属性的值,另一个实例中的属性的值也会改变

    4、组合使用构造函数模式和原型模式

    通过前面的分析,我们应该可以看到构造函数模式和原型模式的优点和缺点啦,构造函数可以创建多个不同属性值的对象,原型模式可以用于定义方法和共享的属性,我们可以将这两种模式结合起来,这种模式现在是使用最广泛的一种模式啦

function Person(name, age) {
 this.name = name;
 this.age = age;
}

Person.prototype = {
 constructor: Person,
 sayName: function() {
  console.log(this.name);
 }
}

var person1 = new Person("Nicholas", 29);
var person2 = new Person("Greg", 27);

person1.sayName(); // Nicholas
person2.sayName(); // Greg
person1.sayName === person2.sayName; // true

    从上面的例子我们可以看到,使用这种模式创建对象,每个实例都会有自己的一份实例属性的副本,但同时又共享着对方法的引用,最大限度地节省了内存,另外,这种混成模式还支持向构造函数传递参数,可谓是集两种模式之长 

    5、动态原型模式

    这种模式主要是将所有信息都封装在了构造函数里,因为在组合构造函数模式和原型模式中,构造函数和原型模式是独立的,有些开发人员会感到很困惑,因此,这种模式也是为了解决这个问题,通过在构造函数中初始化初始化原型,又保持了同时使用构造函数和原型的优点,换句话说,就是可以通过在构造函数中,检查某个应该存在的方法是否有效,来决定是否需要初始化原型

function Person(name, age) {
 this.name = name;
 this.age = age;
 if(typeof this.sayName != "function") {
  Person.prototype.sayName = function() {
   console.log(this.name);
  }
 }
}

var person1 = new Person("Nicholas", 29);
person1.sayName(); // Nicholas

    这里要说明一下,在if语句中的代码,只有在首次调用构造函数时才会执行,之后原型已经得到初始化,不需要再做什么修改了

    6、寄生构造函数模式

    这种模式其实和工厂模式很像,除了使用new操作符并把使用的包装函数叫做构造函数之外,和工厂模式可以说是一模一样的,这种模式的基本思想是创建一个函数,该函数的作用仅仅是封装创建对象的代码,然后再返回新创建的对象

function Person(name, age) {
 var o = new Object();
 o.name = name;
 o.age = age;
 o.sayName = function() {
  console.log(this.name);
 }
 return o;
}

var person1 = new Person("Nicholas", 29);
person1.sayName(); // Nicholas

    寄生构造函数模式和工厂模式真的是很像,那么既然有了工厂模式,为什么还要有寄生构造函数模式呢?其实这个模式主要是用来给js原生的构造函数定义一些新的方法,我们可以看下面这个例子

function SpecialArray() {
 var values = new Array();
 values.push.apply(values, argumens);
 values.toPipedString = function() {
  return this.join("|");
 }
 return values;
}

var colors = new SpecialArray("red","blue");
console.log(colors.toPipedString()); // red|blue

    从上面这个例子我们可以看到,我们在构造函数里面创建了一个新的数组,然后通过push方法初始化这个数组,并且又给数组的实例添加了一个toPipedString方法,并且将所创建的数组返回,因此呢,当我们通过new创建了SpecialArray实例时,其实就得到增加了新方法的数组实例啦,就可以在这个实例上使用我们添加的新的方法toPipedString

    7、稳妥构造函数模式

    在说这种模式之前,要先说一下稳妥对象,稳妥对象就是指没有公共属性,而且其方法也不引用this的对象,稳妥对象最适合在一些安全的环境中,或者防止数据被其他应用程序改动时使用,稳妥构造函数模式遵循与寄生构造函数类似的模式,但是还是有下面的不同,第一个是新创建的对象实例方法不引用this,第二个是不使用new操作符调用构造函数

function Person(name, age) {
 var o = new Object();
 _name = name;
 _age = age;
 o.sayName = function() {
  return _name;
 }
 return o;
}

var person1 = new Person("Nicholas", 29);
person1.sayName(); // Nicholas

    在上面这个例子中,我们在构造函数中创建了一个对象后,可以继续添加一些私有的变量和函数,要修改这些私有的变量和函数,只能通过创建的对象的方法进行访问,这里在对象上创建的方法其实可以看作就是公有方法,比如说这里的_name和_age就是私有变量,而对象o的sayName方法就是访问私有变量的公有方法了,这里除了调用sayName()方法外,没有其它方法可以访问其数据成员

    8、es6中创建对象的方法

    最后要来说下es6中创建对象新增的方法啦,在es6中,引入了 Class(类)这个概念,作为对象的模板,通过class关键字,可以定义类,基本上,ES6 的class可以看作只是一个语法糖,它的绝大部分功能,ES5 都可以做到,新的class写法只是让对象原型的写法更加清晰、更像面向对象编程的语法而已

class Person {
 constructor(name, age) {
  this.name = name;
  this.age = age;
 }
 sayName() {
  console.log(this.name);
 }
}

var person1 = new Person("Nicholas", 29);
person1.sayName(); // Nicholas

    上面这个例子其实就是组合构造函数模式和原型模式的改写,其中,constructor属性直接指向类本身,该方法会默认返回实例对象,在里面定义的属性和方法都是实例本身具有的方法,不是其它实例共享的,而像sayName方法就是定义在原型上的方法了,是所有实例一起共享的

    好啦,今天就介绍到这里了,不知道大家对对象和对象的创建是否有了一个比较详细的了解了呢

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对脚本之家的支持。

相关文章

  • javascript:google 向上向下滚动特效,兼容IE6,7,8,FF

    javascript:google 向上向下滚动特效,兼容IE6,7,8,FF

    这个代码是我之前带网上找的,因为今天再次用到,所以记录下来,免得以后都找不到,我现在想去搜它的说明文档都搜不到!
    2010-08-08
  • JavaScript 闭包在封装函数时的简单分析

    JavaScript 闭包在封装函数时的简单分析

    近才开始系统的研究js,对js的兴趣源于对JQuery的应用。之前只会用js做简单的计算函数,后来由于需要做特效,故接触JQ,看着API,基本的特效都能完成,但相反,如果用js去实现,估计自己很难写得出来,所以下定决心系统的看看js。
    2009-11-11
  • JavaScript WeakMap的具体使用

    JavaScript WeakMap的具体使用

    本文主要介绍了JavaScript WeakMap的具体使用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-02-02
  • javascript 数组去重复(在线去重工具)

    javascript 数组去重复(在线去重工具)

    很多情况下我们需要去掉重复的内容,一般我们都是将很多内容放到一个数组里面,然后再去重复,这里简单为大家整理一下
    2016-12-12
  • JS判断数组中是否有重复值得三种实用方法

    JS判断数组中是否有重复值得三种实用方法

    数组中是否有重复值的判断方法有很多,本文为大家推荐下比较实用的3种方法,感兴趣的朋友可以参考下,希望对大家有所帮助
    2013-08-08
  • js获取对象、数组的实际长度,元素实际个数的实现代码

    js获取对象、数组的实际长度,元素实际个数的实现代码

    下面小编就为大家带来一篇js获取对象、数组的实际长度,元素实际个数的实现代码。小编觉得挺不错的,现在就分享 给大家,也给大家做个参考。一起跟随小编过来看看吧
    2016-06-06
  • js实现中国象棋游戏

    js实现中国象棋游戏

    这篇文章主要为大家详细介绍了js实现中国象棋游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-05-05
  • JS中双击和单击事件冲突的解决方法

    JS中双击和单击事件冲突的解决方法

    这篇文章主要为大家详细介绍了JS中双击和单击事件冲突的解决方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-04-04
  • JS模仿编辑器实时改变文本框宽度和高度大小的方法

    JS模仿编辑器实时改变文本框宽度和高度大小的方法

    这篇文章主要介绍了JS模仿编辑器实时改变文本框宽度和高度大小的方法,涉及javascript鼠标事件及页面元素样式的动态操作技巧,具有一定参考借鉴价值,需要的朋友可以参考下
    2015-08-08
  • javascript 树形导航菜单实例代码

    javascript 树形导航菜单实例代码

    本文章来给大家提供一款适用于网站后台的使用的javascript 树形导航菜单特效代码,有需要了解的同学可以参考一下
    2013-08-08

最新评论