您的位置:首页 > 其它

创建对象和继承的几种方式及区别(1)

2019-07-25 09:50 246 查看
版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。 本文链接:https://blog.csdn.net/qq_35423431/article/details/97037198

面向对象都有类的概念,通过类可以创建任意多个具有相同属性和方法的对象。
每个对象都是基于一个引用类型创建的。
PS:阅读JS高级程序教程第六章笔记

1、对象

创建:new Object() / 对象字面量

var person = new Object();
person.name = "qwe"
person.sayName = function() { ... }
-----------------------------------------------------------------------
var person = {
name: 'qwe',
sayName: function() {... }
}

ES5定义只有内部使用的特性(attribute)时,描述了属性(property)特征。规范是将其放在[[ ]]中。属性分为以下两种:

1)数据属性

包含一个数据值,有4个描述其行为的特性:

[[Configurable]]、[[Enumerable]]、[[Writable]]、[[Value]]

前三个特性默认为true,[[Value]]会根据创建设置的值赋值。

Configurable设置为false后,不能再删除、修改对象的属性

var person = {}
Object.defineProperty(person, "name", {
configurable: false,
value: 'qwe'
})
console.log(person.name) // qwe
person.name = "asd"
console.log(person.name) // qwe

Enumerable表示能否通过for-in循环返回属性

2)访问器属性

[[Configurable]]、[[Enumerable]]、

[[get]]、[[set]]

var book = {
_year: 2004, // _表示只能通过对象方法访问的属性
edition: 1
}
// 定义对象数据属性year
Object.defineProperty(book, "year", {
// 获取属性值,返回_year属性
get: function() {
return this._year
},
// 设置year属性值,判断设置的值是否大于2004 再进行赋值操作
set: function(newValue) {
if(newValue > 2004){
this._year = newValue;
this.edition += newValue - 2004
}
}
})
book.year = 2006 // 赋值 set
console.log(book.year) // 2006 获取 get

PS:
修改属性的默认特性方法:

Object.defineProperty()

读取:
Object.getOwnPropertyDescriptor()

var propertyDes = Object.getOwnPropertyDescriptor(book, 'edition')
console.log(propertyDes.value)

2、创建对象

Object构造函数或者对象字面量可以实现创建单个对象,但是使用同一个接口创建很多对象,会产生大量的重复代码。

1)工厂模式

解决了创建多个相似对象的问题。

function createPerson(name){
var obj = new Object();
obj.name = name;
obj.getName = function(){
return this.name
};
return obj;
}
var person = createPerson('qwe')
console.log(person.getName())

问题:还是不知道一个对象的类型。

2)构造函数模式

ECMAScript中的构造函数可用来创建特定类型的对象。(Object和Array就属于原生的构造函数)

function Person(name){
this.name = name;
this.getName = function(){
return this.name
};
}
var person = new Person('qwe') // new操作符创建实例
console.log(person.getName())

与工厂方法不同:

  • 没有显示的创建对象
  • 直接将属性和方法赋给了this对象
  • 没有return语句
  • 命名以大写字母开头(为了区别于其他的函数)
  • 使用new操作符创建实例

调用构造函数会经历四个步骤:

  • 创建一个新对象
  • 将构造函数的作用域赋给新对象(this指向该对象)
  • 执行构造函数中的代码(为新对象添加属性)
  • 返回新对象

person是Person的实例,Person是person的构造函数,因此person的构造函数属性constructor是指向Person的:

person.constructor == Person
// true

可以用来标识对象的类型,但是检测对象类型,基本上使用

instanceof

person instanceof Person // true
person instanceof Object // true(所有对象都继承Object,函数是对象,函数对象)

PS:

值类型用typeof判断,引用类型用instanceof判断

问题: 每创建一个实例,getName方法都会重新创建一遍,生成不同的Function实例,这是没必要的。
解决: 将函数抽取出来,放到构造函数外,设置成全局的函数

function Person(name){
this.name = name;
this.getName = getName
}
function getName(){
return this.name
}

但是,如果有很多的函数的话,就要定义很多的全局函数,这是不现实的。
这就引申出原型模式。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: