javascript 对象的创建与继承模式
针对JS高级程序设计这本书,主要是理解概念,大部分要点源自书内。写这个主要是当个笔记加总结
存在的问题请大家多多指正!
6.1理解对象
创建对象的两个方法(暂时)
//第一种,通过创建一个Object类型的实例,然后为他添加属性和方法
var person = new Object()
person.name = 'laotie'
person.sayName = function(){
alert(this.name)
}
//第二种简化版
var person = {
name: 'laotie',
sayName: {
alert(this.name)
}
}
6.1.1 类型属性
1.数据属性
JS不能访问的数据属性
Configurable能不能用delete删除 默认trueEnumerable能否通过for-in循环返回属性 默认trueWritable能否修改属性 默认trueValue就是这个属性的属性值 默认undefined
Object.defineProperty()接收三个参数:属性所在的对象,属性的名字和一个描述符对象 描述符对象必须是上面那四个
var person = {}
Object.defineProperty(person, 'name', {\
//我设置了,其中person的属性name,所以name这个属性他就动不了了
writable: false,
value: 'laotie'
})
alert(person.name) //'laotie'
person.name = '666'
alert(person.name) //'laotie'
如果用Object创建的属性一般configurable,enumerable,writable的默认值都是false,如果不用他创建的话就没有限制。
总之这个东西没什么太大实际用处,帮助理解吧
2.访问器属性
Configurable, enumerable跟上面的差不多Get在读取属性时调用的函数Set在写入时调用的属性 get,set默认都为undefined
var book = {
_year: 2004
edition: 1
}
Object.defineProperty(book, 'year', {
//这里放刚才的属性
get: function(){
return this._year
},
set: function(newValue){
if(newValue > 2004){
this._year = newValue
this.edition += newValue - 2004
}
}
})
book.year = 2005
alert(book.edition) //
老方法不介绍了,是直接在对象后面调用__defineGetter__和__defineSetter__,参数里面第一个是属性,第二个穿进去个处理函数
6.1.2定义多个属性
ES5加了个牛逼的Object.defineProperties()方法
第一个参数里放要修改属性的对象 ,第二个加个代码块里面方参数
var book = {}
Object.defineProperties(book,{
_year: {
writable: true,
value:2004
},
edition: {
writable: true,
value: 1
},
set:function(newValue){
if(newValue > 2004){
this._year = newValue
this.edition += newValue - 2004
}
}
})
6.1.3读取属性的特性
Object.getOwnPropertyDescriptor()
var descript = Object.getOwnPropertyDescriptor(book, '_year')
alert(descript.value) //
alert(descript.configurable) //false
6.2创建对象
6.2.1工厂模式
fucntion createPerson(name, age, job){
var o = new Object()
o.name = name
o.age = age
o.job = job
o.sayName = function(){
alert(this.name)
}
return o
}
var person1 = creatPerson('laotie', 26, 'meiyou')
没法解决你这个对象什么类型的,因为对象在里面创建的,很迷
6.2.2构造函数模式
//构造函数首字母大写 Person
function Person(name, age, job){
this.name = name
this.age = age
this.job = job
this.sayName = function(){
alert(this.name)
}
}
//有个new
var person1 = new Person('laotie', 26, 'meiyou')
用instanceof验证是谁的实例
person1 instanceof Object //true
person1 instanceof Person //true
- 如果不按套路用构造函数可以不用new 然后也可以没有变量接着
Person('laotie', 25, '666') //添加对象到window
window.sayName() //‘laotie’
构造函数中的方法在不停的声明function实例,每一个同名function通过新对象的创建都在不停地复制着等于this.sayName = new Function('alert(this.name)')
可以这样改
//构造函数首字母大写 Person
function Person(name, age, job){
this.name = name
this.age = age
this.job = job
this.sayName = sayName
} function sayName(){
alert(this.name)
}
但是这样构建函数的话没有封装性可言,所以要用原型模式
6.2.3原型模式
每个函数都有一个prototype属性指向原型对象
//标准的原型模式函数是没有参数的
function Person(){} Person.prototype.name = 'laotie'
Person.prototype.age = 29
Person.prototype.job = '666'
Person.prototype.sayName = function(){
alert(this.name)
}
缺点:新建的所有对象所有属性都共享,没有传参
只要创建一个新函数, 那他就有一个原型的属性(prototype这个属性),这个属性指向他的原型对象,原型对象自动获得一个constructor属性(叫构造函数的属性),这个属性指向prototype属性所在的函数,新建的实例函数里都会有一个不可见的[[Prototype]]的属性(这个对象在火狐safari和chrome里可以看见,叫__proto__)指向原型对象
原型模式函数创建的对象可以再给属性赋值,赋的值可以掩盖原型对象中的值
delete你自己赋的值之后原型对象里的值还可以用
person1.hasOwnProperty('name') //可以看有无自己赋值的属性,有事true ,没有false
'name' in person1 //不管是自己的属性还是原型对象里的属性,只要有值就是true
简单点的设置prototype
function Person(){}
Person.prototype = {
//一般加上constructor: Person 要不然构造函数就跑到Object了
constructor: Person
name:'laotie',
sayName: function(){
alert(this.name)
}
}
新建对象是一定要在构造的后面哈,在前面建对象的话会断开和新建的原型对象的链接
function Person(){}
var person1 = new Person()
//相当于重新设置了Person的原型对象,现在的原型对象和person不是同一个了,所以person1中没有sayName这个函数
Person.prototype = {
constructor: Person
name:'laotie',
sayName: function(){
alert(this.name)
}
}
person1.sayName() //error
有个很大的毛病,就是原型模式函数不能自己传参,所以无论新建多少对象都是一个德行,没有属于自己的属性
6.2.4 把构造函数模式和原型模式组合一波
构造的定义不一样的属性,而原型模式构造一样的属性
function Person(name,age,job){
this.name = name
this.age = age
this.job = job
}
Person.prototype = {
constructor: Person,
sayName: function(){
alert(this.name)
}
}
6.3继承
6.3.1原型链
原型模式构造函数:
- 每个构造函数都会都会有一个原型对象,原型对象contrustor指向构造函数,实例对象[[prototype]]属性指向原型对象。
原型链就是把superType的实例对象给subType构造函数当原型。
还跟原型构造函数要注意的一样,就是在新建实力之后更改构造函数的原型,要不然就会断绝实例对象和新原型对象之间的联系
function SuperType(){
this.property = true
} SuperType.prototype.getSuperValue = function(){
return this.property
} function SubType(){
this.subproperty = false
} SubType.prototype = new SuperType() SubType.prototype.getSubValue = function(){
return this.subproperty
} var instance = new SubType() alert(instance.getSuperValue) //true原型模式参数传递不方便,所以菜的一批,所以借用构造函数
6.3.2 借用构造函数
就是在SubType里call或者apply一个SuperType,相当于在SubType调用了SuperType里的所有东西,所以就顺理成章的继承过来了
function SuperType(){
this.color = ['red', 'blue']
}
function SubType(){
SuperType.call(this)
}
var instance1 = new SubType()
instance1.colors.push('black')
alert(instance1.colors) //red,blue,black
var instance2 = new SubType()
alert(instance.colors) //red,blue
与原型的不同就是可以传参数,然后用call的第二个后面或者apply的第二个函数赋值
但是问题是方法都在构造函数里,函数没法复用,所以就用组合式的比较吊,可以传参,可以函数复用
6.3.4 组合式继承
就是上面说的,用借用构造函数传参和设定基本属性,用原型链来做方法的复用
function SuperType(name) {
this.name = name
this.colors = ['red', 'blue']
}
SuperType.prototype.sayName = function() {
alert(this.name)
}
function Subtype(name, age) {
//第二处这里在call的时候又引入了name 和color属性。所以重复了,这也是组合继承的缺点
SuperType.call(this, name)
this.age = age
}
//第一处在设置原型对象时候在原型对象中 有name 和color属性了,看上面⤴️
Subtype.prototype = new SuperType()
Subtype.prototype.constructor = SubType
Subtype.prototype.sayAge = function (){
alert(this.age)
}
这样的好处是可以传入参数可以有自己的属性,然后又可以有共同的函数
6.3.4 原型式继承
Object.creat()这个方法,可以放一个或者两个参数,一个参数的时候是第一个是一个对象
第二个函数是可以附加一些属性,通过{name:'laotie'}这样的直接加进去
原理类似下面
function object(o){
function F(){}
F.prototype = o
return new F()
}
其实就是讲一个对象丰富了加了一些属性,然后再返回一个实例对象。有一个弊端,没有creat之前的内容和属性始终会共享。
6.3.5 寄生式继承
这个书上也没有仔细讲,给我感觉就是传进来一个对象,然后通过内部加强一些内容再返还出去
function creatAnother(original){
var clone = object(original)
clone.sayhi = funciton(){
alert('hi')
}
return clone
}
6.3.6 寄生组合式继承
尼古拉斯挑了个原型链继承的和借用继承的毛病,就是里面的参数会重复的建,占用内存,所以为了优化,就找了个寄生组合继承,给我感觉像是借用加上原型式(不是原型链继承模式是原型式)模式
function inheritPrototype(subType,SuperType){
var prototype = object(SuperType.prototype)
prototype.constructor = subType
subtype.prototype = prototype
}
这个不就是原型式继承吗?为啥要带上寄生式,感觉没寄生式啥事。
然后剩下的用借用就行了
完整代码:
function SuperType(name){
this.name = name
this.colors = ['red','blue']
}
SuperType.prototype.sayName = function(){
alert(this.name)
}
function SubType(name,age){
SuperType.call(this,name)
this.age = age
}
inheritPrototype(subType,SuperType)
SubType.prototype.sayAge = function(){
alert(this.age)
}
javascript 对象的创建与继承模式的更多相关文章
- JavaScript 对象的创建和对6种继承模式的理解和遐想
JS中总共有六种继承模式,包括原型链.借用构造函数.组合继承.原型式继承寄生式继承和寄生组合式继承.为了便于理解记忆,我遐想了一个过程,对6中模式进行了简单的阐述. 很长的一个故事,姑且起个名字叫 ...
- JavaScript对象的创建
原文 简书原文:https://www.jianshu.com/p/6cb1e7b7e379 大纲 前言 1.简单方式创建对象的方法 2.工厂模式创建对象 3.构造函数模式创建对象 4.原型模式创建对 ...
- JavaScript 对象的创建和操作
<script> // 对象是属性的无序集合,每个属性都是一个名/值对. 属性名称是一个字符串. // 对象种类 // 内置对象(nativ ...
- JavaScript对象的创建之使用json格式定义
json: javascript simple object notation. json就是js的对象,但是它省去了xml中的标签,而是通过{}来完成对象的说明. 定义对象 var person = ...
- Greenplum+Hadoop学习笔记-14-定义数据库对象之创建与管理模式
6.3.创建与管理模式 概述:DB内组织对象的一种逻辑结构.一个DB内能够有多个模式.在未指定模式时默认放置在public中.能够通过"\dn"方式查看数据库中现有模式: test ...
- Greenplum中定义数据库对象之创建与管理模式
创建与管理模式 概述:DB内组织对象的一种逻辑结构.一个DB内能够有多个模式.在未指定模式时默认放置在public中.能够通过"\dn"方式查看数据库中现有模式. testdw=# ...
- JavaScript对象的创建之基于构造方法+原型方式
为了解决原型所带来的问题,此处需要通过组合构造方法和原型来实现对象的创建,将属性在构造方法中定义,将方法在原型中定义.这种有效集合了两者的优点,是目前最为常用的一种方式. function Perso ...
- Javascript对象的创建模式 -- 深入了解Javascript
/* 一.模式1:命名空间(namespace) 优点:减少全局命名所需的数量,避免命名冲突或过度 */ // 更简洁的方式 var MYAPP = MYAPP || {}; //定义通用方法 MYA ...
- 菜鸟快飞之JavaScript对象、原型、继承(三)
正文之前需要声明的一点是,菜鸟系列博文全是基于ES5的,不考虑ES6甚至更高版本. 继承 由于我个人不是学计算机的,所以对于很多东西只是知其然,不知其所以然.就像这个继承,刚开始学JavaScript ...
随机推荐
- django学习-数据库操作接口API--(CRUD)
初试API(数据库操作接口CRUD) 现在我们进入交互式python命令行,尝试一下django为你创建的各种API,通过以下命令打开python命令行: py -3 manage.py shell进 ...
- springboot+springcloud微服务项目全套资料(笔记+源码+代码)
最近好几天没有写博客了,由于时间的太忙了,项目要做.各种资格证要考试,实在没有时间写了,今天正好赶上有闲暇的一刻,应许多的爱好者的要求发一份微服务项目的资料,此资料十分完整,且是最新的.希望各位读者能 ...
- thread_asyncio
thread_asyncio # 使用多线程:在携程中集成阻塞io import asyncio from concurrent.futures import ThreadPoolExecutor i ...
- 实战接口开发:python + flask + mysql + redis(根据反馈,持续细化更新。。。)
前言 自动化已经成为测试的必备技能之一了,所以,很多想跳槽的测试朋友都在自学,特别是最实用的接口自动化, 但是很多人因为没有可以练手的项目而苦恼,最终导致缺乏实战经验,其实,完全可以自己开发个简单项目 ...
- Cannot resolve reference to bean 'mongoTemplate' while setting bean property 'mongoOperations'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with na
问题: Springboot 启动时出错,报没法创建bean的错误,看到nested最后是关于mongoTemplate的错误. 过程: 看网上大多说的是修改mongoTemplate的配置,但是sp ...
- SQL Server的字符类型
Tip1. Char/Varcahr均为非Unicode字符,意味着放非英文字符放进去会需要进行编译,将来可能会出现问题,如果这个字段将来可能要输入中文韩文日文等,建议用Nchar或Nvarchar. ...
- 【CF438D】The Child and Sequence(线段树)
点此看题面 大致题意: 给你一个序列,让你支持区间求和.区间取模.单点修改操作. 区间取模 区间求和和单点修改显然都很好维护吧,难的主要是区间取模. 取模标记无法叠加,因此似乎只能暴力搞? 实际上,我 ...
- 请求与上传文件,Session简介,Restful API,Nodemon
作者 | Jeskson 来源 | 达达前端小酒馆 请求与上传文件 GET请求和POST请求 const express = require('express'); const app = expre ...
- [LeetCode] 633. Sum of Square Numbers 平方数之和
Given a non-negative integer c, your task is to decide whether there're two integers a and b such th ...
- Java Web 之 SSM笔记
好久没有写博文了呀呀呀........博客园的MarkDown还是...算了吧 自定义 Restful 风格结果集 参考资料 [SpringBoot专题]统一异常处理和统一数据返回前言实践运行结果 如 ...