最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • JavaScript创建对象的方法演变

    正文概述 掘金(chenwl)   2021-08-13   489

    一、工厂模式->构造函数模式:解决对象类型识别问题

    //工厂模式
    function createPerson(name,age){
    	var o=new Object();
    	o.name=name;
    	o.age=age;
    	o.sayName=function(){
    		alert(this.name);
    	}
    	return o;
    }
    var p=createPerson("Alice",20);
    console.log(p);
    
    //构造函数模式
    function Person(name,age){
    	this.name=name;
    	this.age=age;
    	this.sayName=function(){
    		alert(this.name);
    	}
    }
    var p=new Person("Cindy",20);
    console.log(p);
    

    从两者输出的实例对象开看,原型链是不一样的。

    JavaScript创建对象的方法演变

    工厂模式原型链:实例对象->Object构造函数的原型对象,p.constructor输出Object。

    构造函数模式原型链:实例对象->Person构造函数的原型对象->Object构造函数的原型对象,p.constructor输出Person。

    这点差异使得构造函数模式可以用来进行对象识别,就是说可以直到这个对象是什么类型对象。可以使用constructor和instanceof进行类型判断。

    console.log(p.constructor==Person)  //true
    console.log(p instanceof Person)    //true
    

    二、构造函数模式->原型模式:解决创建多对象时代码复用问题

    1、对象属性搜索机制:沿着原型链进行查找,找到就中止查找。首先搜索对象实例本身是否有该属性,没有则沿着原型链(__proto__指向的对象)去查找原型对象中是否有该属性,直到找到原型链的最后一个原型对象。

    2、对象、构造函数与原型对象的关系:一个构造函数对应一个函数原型对象,构造函数创建出来的n个对象对应同一个构造函数原型对象(就是构造函数的原型对象)。

    基于以上两点,要想实现n个对象共享属性或方法,就把这些属性和方法定义在原型对象上,可以接受不少内存空间。而且原型具有动态性,修改原型中的属性值,可以在所有对象得到反映。

    但是单独使用原型模式弊端会很明显,函数定义在原型上回很合适,但是如果引用类型放在原型上,就会导致所有对象都共享这个引用类型。

    三、构造函数模式和原型模式相结合:处理共有与独有的关系,是最优的模式

    构造函数定义对象独有的属性,原型上定义对象共有的属性。

    function Person(name,age){
    	this.name=name;
    	this.age=age;
    }
    Person.prototype.sayName=function(){
    	console.log(this.name);
    }
    
    var p1=new Person("Cindy",20);
    var p2=new Person("Alice",25);
    p1.sayName()  //Cindy
    p2.sayName()  //Alice
    

    四、ES6 class语法——构造函数模式和原型模式的语法糖

    class Person1{
    	constructor(name,age){
    		this.name=name
    		this.age=age
    	}
    	country="China";
    	sayName=function(){
    		alert(this.name);
    	}
    	sayContry(){
    		alert(this.country);
    	}
    }
    var p=new Person1("Aclie",22)
    

    对象p输出的结果是:

    Person1 {country: "China", name: "Alice", age:20, sayName: ƒ}
    	age: 20
    	country: "China"
    	name: "Alice"
    	sayName: ƒ ()
    	[[Prototype]]: Object
    		constructor: class Person1
    		sayContry: ƒ sayContry()
    		[[Prototype]]: Object
    			constructor: ƒ Object()
    			...
    

    1、构造器函数constructor()不是必须的,但是写个构造函数有助于通过传参,定义对象的独有属性。构造器中定义的属性时对象实例的属性。

    2、class中通过表达式定义的属性,无论是基本类型(country)、引用类型还是函数(sayName),都是对象实例的属性。

    3、class中使用函数声明定义的函数,才是构造函数原型上的方法。

    五、动态原型模式——构造函数模式和原型模式封装在构造函数中

    我觉得有了class语法糖之后,就不需要用这种方式强硬封装了。

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

    六、构造函数模式延伸的两种特殊模式——特殊用途(扩展篇)

    (一)寄生构造函数模式

    构造函数不返回值,就是常规的构造函数模式。

    构造函数返回值,就是寄生构造函数模式。函数调用上下文赋值给这个返回的对象,即this指向是这个新对象。

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

    看到Person这个函数和工厂模式是一样的,但是调用时用new关键字调用,这种方式下,原型链也是,实例对象->Object构造函数的原型对象,因此无法用来识别对象类型,也没什么共享优势,那么它的用途是什么呢?

    JavaScript有很多内置对象,比如Array,如果想给内置对象添加某些方法方便使用,就可以借助寄生构造器模式实现。

    function SpecialArray(){
    	var arr=new Array();
    	arr.push(...arguments);
    	//添加一个特殊方法
    	arr.toPipedString=function(){
    		return this.join("|");
    	}
    	return arr;
    }
    console.log(colors.toPipedString());  //输出 red|blue|green
    console.log(colors.length)    //输出 3
    colors.slice(0,2)  //输出 ["red", "blue"]
    

    可以看到,使用寄生构造器模式改造的Array对象,不仅有新增的方法,还可以使用Array对象原来的属性和方法,简直不要太nice。

    (二)稳妥构造函数模式

    这个模式适用于那种很特殊的this和new关键字都不给使用的环境。乍一看和工厂模式的代码几乎没有出入,除了不使用this关键字。和寄生构造器模式一样,无法用来识别对象类型,也没什么共享优势,最大的优势就是安全。

    function createPerson(name,age){
    	var o=new Object();
    	o.name=name;
    	o.age=age;
    	o.sayName=function(){
    		alert(name); 
                     //注意这里的差异,这个name在外层cretePerson的变量对象上,是可以沿着作用域链访问到的
    	}
    	return o;
    }
    var p=createPerson("Alice",20);
    console.log(p);
    p.sayName()  //输出"Alice"
    

    起源地下载网 » JavaScript创建对象的方法演变

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元