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

面向对象都有类的概念,通过类可以创建任意多个具有相同属性和方法的对象。
每个对象都是基于一个引用类型创建的。
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
	}

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
JavaScript中实现继承方式有以下几种: 1. 原型链继承 优点:简单方便,易于理解和实现。 缺点:父类的引用属性会被多个实例共享,可能会出现意外修改;子类无法向父类构造函数传递参数。 示例代码: ```javascript function Animal() { this.species = 'animal'; } function Cat() {} Cat.prototype = new Animal(); ``` 2. 借用构造函数继承 优点:可以在子类构造函数中向父类构造函数传递参数;解决了父类引用属性被多个实例共享的问题。 缺点:无法实现函数的复用。 示例代码: ```javascript function Animal(name) { this.name = name; } function Cat(name) { Animal.call(this, name); } ``` 3. 组合继承 优点:综合了原型链继承和借用构造函数继承的优点,既可以实现函数的复用,又可以向父类构造函数传递参数。 缺点:父类构造函数会被调用两次,造成了一些不必要的消耗。 示例代码: ```javascript function Animal(name) { this.name = name; } Animal.prototype.sayHello = function() { console.log('Hello, my name is ' + this.name); }; function Cat(name) { Animal.call(this, name); } Cat.prototype = new Animal(); Cat.prototype.constructor = Cat; ``` 4. 原型式继承 优点:简单方便,可以在不必创建构造函数的情况下实现继承。 缺点:引用属性会被共享,可能会造成意外修改。 示例代码: ```javascript function createObject(obj) { function F() {} F.prototype = obj; return new F(); } var animal = { species: 'animal' }; var cat = createObject(animal); ``` 5. 寄生式继承 优点:可以在不必创建构造函数的情况下实现继承,可以为对象添加专门的方法。 缺点:引用属性会被共享,可能会造成意外修改。 示例代码: ```javascript function createObject(obj) { var clone = Object.create(obj); clone.sayHello = function() { console.log('Hello, my name is ' + this.name); }; return clone; } var animal = { species: 'animal' }; var cat = createObject(animal); ``` 总体来说,不同的继承方式各有优缺点,应根据具体的需求来选择合适的方式

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值