摘要:理解对象创建方式函数生成和字面量例如构造函数方式调用函数字面量属性类型数据属性能否修改属性能否通过循环获取能否修改通过方法修改默认属性例如值没有改变访问器属性函数特性例如读取创建对象工厂模式定义本义是将创建相同或相似对象的过程进行封装,只需
6.1理解对象
创建方式:函数生成 和 字面量
例如:
var a = new Object(); // new 构造函数方式 var a = Object(); // 调用函数 var a = {}; // 字面量属性类型
(1)数据属性:[[configurable]](能否修改属性), [[enumerable]](能否通过for in 循环获取),[[writable]](能否修改),[[value]], 通过Object.defineProperty(obj, proper, properObj)方法修改默认属性
例如:
var a = { name: "jiang" }; console.log(Object.getOwnPropertyDescriptor(a, "name")); // {value: "jiang", writable: true, enumerable: true, configurable: true} Object.defineProperty(a, "name", { "writable": false}); a.name = "zhong"; console.log(Object.getOwnPropertyDescriptor(a, "name")); // {value: "jiang", writable: false, enumerable: true, configurable: true} // 值没有改变
(2)访问器属性:函数(getter(),setter), 特性([[Configuable]], [[Enumerable]], [[Get]], [[Set]])
例如:
var a = { name: "jiang" }; Object.defineProperty(a, "sex", { get: function(){ return 1; }, }); a.name = "zhong"; console.log(a); console.log(a.sex);
(3)读取:Object.getOwnPropertyDescriptor()
6.2创建对象 工厂模式定义:本义是将创建相同或相似对象的过程进行封装,只需调用封装后的函数就可以获取对象
解决的问题:类似的对象不用写重复的代码
带来的问题:创建的对象没有类型标识
function factory(name){ var o = {}; 0.name = name; o.action = function(){}; return o; };// 在这里factory就是工厂模式的工厂 var instance1 = facroty("san"); var instance2 = facroty("si");构造函数
定义:形如:function A(){};的函数, 通过new来进行实例化
解决的问题:同一个构造函数产生的实例类型项目(可以通过instanceOf鉴定), 实例间共享原型对象的属性
特点:构造函数内部的this指的是当前的实例对象
带来的问题:每个方法都属于不同的实例,就是没创建一个实例方法就会重新创建一遍
function Factory(name){ this.name = name; this.action = function(){}; }; var instance1 = new Factory("san"); var instance2 = new Factory("si"); console.log(instance1 instanceof Factory); // true console.log(instance2 instanceof Factory); // true原型模式
定义:一个对象中属性和方法被所有实例所共享(共享实例都可以看成是这个复制品),这样的对象就是原型对象
解决的问题:构造函数的方法和属性在各个实例间是共享的
function Func(){}; Func.prototype.name = "xiaotu"; Func.prototype.action = function(){ console.log(this.name,"跑路"); }; var instance1 = new Func(); var instance2 = new Func(); instance1.action(); // xiaotu 跑路 instance2.action(); // xiaotu 跑路
特点:(1)通过new 构造函数产生实例对象,构造函数默认属性prototype指向实例对象的原型对象, 原型对象的默认的constructor(constructor属性被实例对象所共享)属性又指向构造函数, 实例对象通过[[ProtoType]]指向实例得原型对象
function Func(){}; console.log(Func.prototype); // {constructor: ƒ} console.log(Func.prototype.constructor); // ƒ Func(){} var instance1 = new Func(); // instance1可以访问原型的constructor console.log(instance1.constructor) // ƒ Func(){} console.log(instance1.__proto__) // {constructor: ƒ} // 关系图(*代表指向目标) constructor *---------------------------- 函数(Func) ----------------------* 原型对象(Func.prototype) (prototype) * / (new) (_proto_)/(Object.getPrototypeOf(instance1)) / / / / / 对象实例(instance1)
(2)实例对象与原型对象之间的对应关系可以通过isProtoTypeOf()来判断, 可以通过getProtoTypeOf()获取对象实例的原型对象
function Func(){}; var instance1 = new Func(); console.log(Func.prototype.isPrototypeOf(instance1)); // true console.log(Object.getPrototypeOf(instance1)); // {constructor: ƒ}
(3)实例对象与原型对象的属性可以重复但不会覆盖,只是搜索时优先搜索实例对象的
function Func(){ this.name = "jiang"; }; Func.prototype.name = "zhong"; var instance1 = new Func(); console.log(instance1.name); // jiang delete instance1.name; console.log(instance1.name); // zhong
(4)hasProprtyOf():判断对象实例中是否有此属性, in:判断对象实例和原型对象中是否由此属性, for - in 循环遍历包括原型和实例的属性, Object.keys() 返回所有实例的属性
function Func(){ }; Func.prototype.name = "zhong"; var instance1 = new Func(); console.log(instance1.hasOwnProperty("name")); // false console.log("name" in instance1); // true
(5)原型对象添加属性的方式:"."(增量添加) "{}"(覆盖添加此时有默认的constructor指向Object)
带来的问题:如果原型对象的属性是引用类型的那么实例对象和原型对象的这个属性是同一个引用, 所以有了组合原型模式和构造函数,将引用属性定义在构造中就没这个问题了
注:当通过实例去写值得时候如果实例不存在该属性则会去原型属性中查找,如果在原型中是引用类型的属性则对原型属性修改,如果是基本类型的则在实例中新建属性并赋值
function Func(){ this.legs = ["left"]; }; Func.prototype.arms = ["right"]; var instance1 = new Func(); instance1.legs.push("right"); instance1.arms.push("left"); var instance2 = new Func(); console.log(instance2.legs); // ["left"] console.log(instance2.arms); // ["right", "left"] console.log(instance2.hasOwnProperty("arms")); // false console.log(instance2.__proto__.hasOwnProperty("arms")); // true组合原型模式和构造函数:原型模式负责定义实例共享的属性和方法, 构造函数定义每个实例特定的方法和属性
如上例(5)6.3继承
只支持实现继承(相对于接口继承)原型链
定义:将一个(函数A)对象实例a赋值给某个函数B的原型B.prototype,那么B的实例b就拥有了a的属性,如果让A的原型的值等于另一个实例,a也拥有了其他对象的值, 如此形成了原型链 解决的问题:让对象之间实现了继承
function SuperFunc(){ this.name = "big-jiang"; }; function SubFunc(){ this.name = "small-jiang"; }; var superFunc = new SuperFunc(); SubFunc.prototype = superFunc; var subFunc = new SubFunc(); console.log(subFunc.name); // "small-jiang" console.log(subFunc.__proto__.name); // "big-jiang" SuperFunc.prototype = new ... // 继续继承成链
特点: (1)所有对象都继承了Object, 可以通过对象原型的原型(最后一层原型)的constructor是否指向Object的原型去判断
function SuperFunc(){ this.name = "big-jiang"; }; function SubFunc(){ this.name = "small-jiang"; }; console.log(SuperFunc.prototype.constructor == Object); // false 应是SuperFunc console.log(SuperFunc.prototype.__proto__.constructor == Object); // true var superFunc = new SuperFunc(); SubFunc.prototype = superFunc; console.log(SubFunc.prototype.constructor == SubFunc); // false 应是SuperFunc console.log(SubFunc.prototype.constructor == SuperFunc); // true console.log(SubFunc.prototype.__proto__.constructor == SuperFunc); // true console.log(SubFunc.prototype.__proto__.__proto__.constructor == Object); // true
(2)确定某原型是不是对应某实例间可以通过instanceOf和isPrototypeOf()
function SuperFunc(){ this.name = "big-jiang"; }; function SubFunc(){ this.name = "small-jiang"; }; var superFunc = new SuperFunc(); SubFunc.prototype = superFunc; var subFunc = new SubFunc(); console.log(subFunc instanceof SubFunc); // true console.log(subFunc instanceof SuperFunc); // true
带来的问题:父级的实例变成了子级的原型,父级的属性是引用类型的话就会带来所有实例共享的问题,不能向父级构造函数传递参数
function SuperFunc(){ this.arms = ["left"]; }; function SubFunc(){ }; var superFunc = new SuperFunc(); SubFunc.prototype = superFunc; var subFunc1 = new SubFunc(); subFunc1.arms.push("right"); var subFunc2 = new SubFunc(); console.log(subFunc2.arms); // ["left", "right"]借用构造函数
定义:在子函数中通过apply或者call将当前作用域传给父函数来实现继承 解决的问题:这样就不会有原型带来的共享引用属性的问题, 也可以在apply或者call中传递参数
function SuperFunc(name){ this.name = name; }; function SubFunc(){ this.name = "zhong"; SuperFunc.call(this, "jiang"); }; var subFunc = new SubFunc(); console.log(subFunc.name); // jiang
带来的问题:复用性差,父级原型中的属性方法,自己都不能获取到组合继承
定义:将借用构造函数和作用域链两种方式结合起来使用 解决的问题:将前两种继承方式的优点结合起来, 缺点可以选择性去避免
function SuperFunc(name){ this.name = name; this.arms = ["left"]; }; function SubFunc(){ SuperFunc.call(this, "jiang"); }; var superFunc = new SuperFunc(); SubFunc.prototype = superFunc; var subFunc = new SubFunc(); subFunc.arms.push("right"); var subFunc2 = new SubFunc(); console.log(subFunc2.arms); // "left"
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/100487.html
摘要:对象数组初始化表达式,闯关记之上文档对象模型是针对和文档的一个。闯关记之数组数组是值的有序集合。数组是动态的,根闯关记之语法的语法大量借鉴了及其他类语言如和的语法。 《JavaScript 闯关记》之 DOM(下) Element 类型 除了 Document 类型之外,Element 类型就要算是 Web 编程中最常用的类型了。Element 类型用于表现 XML 或 HTML 元素...
摘要:理解的函数基础要搞好深入浅出原型使用原型模型,虽然这经常被当作缺点提及,但是只要善于运用,其实基于原型的继承模型比传统的类继承还要强大。中文指南基本操作指南二继续熟悉的几对方法,包括,,。商业转载请联系作者获得授权,非商业转载请注明出处。 怎样使用 this 因为本人属于伪前端,因此文中只看懂了 8 成左右,希望能够给大家带来帮助....(据说是阿里的前端妹子写的) this 的值到底...
摘要:对象在中,除了数字字符串布尔值这几个简单类型外,其他的都是对象。那么在函数对象中,这两个属性的有什么区别呢表示该函数对象的原型表示使用来执行该函数时这种函数一般成为构造函数,后面会讲解,新创建的对象的原型。这时的函数通常称为构造函数。。 本文原发于我的个人博客,经多次修改后发到sf上。本文仍在不断修改中,最新版请访问个人博客。 最近工作一直在用nodejs做开发,有了nodejs,...
摘要:然后将构造函数的原型设为,便实现了对象继承。首先,我们定义一个构造函数,并在其中定义一个局部变量。这里的是局部变量,其作用域仍然存在是闭包现象,而非对象属性。 Javascript是动态的,弱类型的,解释执行的程序设计语言。 Javascript极其灵活,支持多种程序设计范式:面向对象、指令式、函数式。JavaSCript最初被用于浏览器脚本,现在已经是所有主流浏览器的默认脚本语言。浏...
摘要:可嵌入动态文本于页面,对浏览器事件作出响应,读写元素,控制等。年月,发布了一款面向普通用户的新一代的浏览器版,市场份额一举超过。网景将这门语言作为标准提交给了欧洲计算机制造协会。线程和的并发执行都是线程安全的。后面会详细讲解对象类型的转换。 本文由云+社区发表作者:殷源,专注移动客户端开发,微软Imagine Cup中国区特等奖获得者 JavaScript越来越多地出现在我们客户端开...
摘要:在中,并没有对抽象类和接口的支持。例如,当对象需要对象的能力时,可以有选择地把对象的构造器的原型指向对象,从而达到继承的效果。本节内容为设计模式与开发实践第一章笔记。 动态类型语言 编程语言按数据类型大体可以分为两类:静态类型语言与动态类型语言。 静态类型语言在编译时已确定变量类型,动态类型语言的变量类型要到程序运行时,待变量被赋值后,才具有某种类型。 而JavaScript是一门典型...
阅读 580·2021-11-18 13:12
阅读 1293·2021-11-15 11:39
阅读 2457·2021-09-23 11:22
阅读 6121·2021-09-22 15:15
阅读 3629·2021-09-02 09:54
阅读 2294·2019-08-30 11:10
阅读 3220·2019-08-29 14:13
阅读 2899·2019-08-29 12:49