秒懂JS创建对象的方式

一、创建单个对象实例

  1. 构造函数创建对象:var obj=new Object(); obj.属性名=属性值; 添加属性
  2. 对象字面量 obj{属性名:属性值,…}
  • 问题:使用一个接口创建很多对象,产生大量重复代码
  • 解决:工厂模式

二、工厂模式

  • 用函数封装接口创建对象的细节,调用函数创建多个对象。
	function createPerson(name, age, job) {
		var obj = new Object();
		obj.name = name;
		obj.age = age;
		obj.job = job;
		obj.sayname = function() {
			console.log(this.name);
		}
		return obj; //创建一个新对象,将对象返回
	}
	
	var obj1 = createPerson('张三', 20, '软件工程师');
	var obj2 = createPerson('李四', 22, '软件工程师');
	
  • 问题:不能做到函数复用

三、构造函数模式

  • 构造函数首字母大写
  1. 使用new 创建对象,没有显式创建对象
  2. 构造函数的作用域赋值给新对象,this指向这个新对象,直接将属性和方法赋值给this
  3. 构造函数中,不写return语句 或 return 基本类型; 会将this作为返回值。 return对象; 会将对象作为返回值
	function Person(name, age, job) {
		this.name = name;
		this.age = age;
		this.job = job;
		this.sayname = function() {
			console.log(this.name);
		}
	}
	
	var obj3 = new Person('张三', 20, '软件工程师');
	var obj4 = new Person('李四', 22, '软件工程师');
	
	console.log(obj3.sayname==obj4.sayname);//false

使用new 操作符调用构造函数创建实例的过程

  1. 创建一个新对象
  2. 将构造函数作用域赋值给新对象,this指向新对象
  3. 执行构造函数中的代码,为新对象添加属性
  4. 返回新对象 return this;

构造函数作为普通函数 直接调用是给window添加属性和方法

构造函数模式的缺点

  • 每个方法都要在每个实例上重新创建一遍。因为方法(函数)是对象,每定义一个方法,就是实例化了一个对象。
  • 解决:原型模式

四、原型模式

  • 每个函数都有原型属性prototype ,是一个指针,指向函数的原型对象
  • 原型对象,可以让所有对象实例共享所有它所包含的属性和方法。
  • 原型模式创建对象: 在原型上添加属性和方法 Person.prototype.属性名=‘属性值’
	function Person() {//构造函数
	
	}
	// 在原型上添加属性和方法
	Person.prototype.name = '张三';
	Person.prototype.age = '21';
	Person.prototype.job = '前端攻城狮'
	Person.prototype.sayName = function() {
		console.log(this.name);
	}
	//必须先重写原型再创建实例对象
	var person1=new Person();
	var person2=new Person();
	
	console.log(person1.sayName==person2.sayName);//true  引用同一个方法
	

原型、构造函数 、实例的关系

  • 实例对象的constructor属性指向构造函数。person.constructor == Person

  • 构造函数原型对象的constructor属性指向该构造函数。Person.prototype.constructor==Person

  • 构造函数的prototype属性指向构造函数的原型对象(简称原型)

  • 构造函数与原型之间类似双向链表的关系

  • 实例对象的__proto__ 属性直接指向构造函数的原型对象。兼容性:safari,firefox,chrome可以使用
    person.__proto__==Person.prototype

  • 构造函数和实例的关系: 实例 instanceof 原型链中的构造函数 返回true

  • 原型和实例的关系:

    1. 原型.isPrototypeOf(实例)方法判断对象之间是否存在原型关系,存在 返回true
    2. Object.getPrototypeOf(实例); 返回对象的原型。支持IE9+

原型链:当代码读取某个对象的属性时,从实例本身构造函数开始查找,如果没有找到,查找__proto__ 指向的原型对象。

自身属性和原型属性

  • 优先访问自身属性
  • 使用null清空自身属性,再次访问该属性时不能访问到原型上的同名属性。
  • 用delete删除自身属性,delete person.name; 会获取到原型属性。

区分自身属性和原型属性

  1. 实例.hasOwnProperty(‘属性’) 方法继承于Object
    • 检测一个属性存在于实例中还是原型中,在实例中,返回true
  2. ‘属性’ in 实例; in操作符 可以通过对象访问到给定属性时(无论是实例中还是原型中)返回true。

原型模式 使用对象字面量添加原型属性 的问题

问题一:使用单独的Person.prototype 添加属性时,会保留原型中自带的constructor属性。
使用对象字面量添加属性时 会重写原型对象 ,失去默认的constructor属性。原型指向新的内存空间。

  • 解决: 在原型里 手动添加 constructor属性 指向构造函数

问题二:先创建实例对象,再使用对象字面量添加原型属性时,不能使用原型中的属性和方法。

  • 原型指向新的地址,构造函数可以自动指向新的地址,而实例仍然指向旧的原型地址.
  • 解决:创建对象写在原型下面。

原型模式 自身的问题

  • 使用实例对象可以修改 原型中引用类型的属性,而这个属性被所有实例共享

五、组合使用构造函数 和 原型模式 —— 创建自定义类型的常见方式

  • 构造函数定义实例属性
  • 原型上定义方法和共享的属性
	//属性写在构造函数里面,每个对象都有自己的属性	
	function Person(name, age, job){
		this.name = name;
		this.age = age;
		this.job = job;
		this.friends=['lily','nacy'];//引用类型的属性值 
		
	}
	Person.prototype={ 			
		constructor:Person,
	//方法写在原型里,实例可以共享
		sayName:function(){
			console.log(this.name);
		}
	}
	
	var person1=new Person('张三',29,'软件工程师');
	var person2=new Person('李四',39,'医生');
	person1.friends.push('tom');
	
	//引用类型的属性值 不共享
	console.log(person1.friends);//(3) ["lily", "nacy", "tom"]
	console.log(person2.friends);//(2) ["lily", "nacy"]
	
	console.log(person1.sayName==person2.sayName);//true  指向同一个地址
	

六、动态原型模式

  • 将独立的构造函数和原型封装在构造函数中,仅在必要时初始化原型
  • 不能使用对象字面量重写原型
	function Person(name, age, job){
		this.name = name;
		this.age = age;
		this.job = job;
		if(typeof this.sayName != 'function'){
			Person.prototype.sayName=function(){
				console.log(this.name);
			}
			
		}
	}
	
	var obj1=new Person('lily',25,'后勤');
	var obj2=new Person('nacy',25,'财务');
	obj1.sayName();//lily
	obj2.sayName();
	console.log(obj1.sayName== obj2.sayName)//true  共享原型方法	
	

七、寄生构造函数模式

  • 类似于 工厂模式+构造函数模式
function Person(name, age, job){
				var o=new Object();
				o.name=name;
				o.age = age;
				o.job = job;
				o.sayName=function(){
					console.log(this.name);	
				}
				
				return o;
			}
			
			var obj=new Person('lily',25,'后勤');
			obj.sayName();//lily

八、稳妥构造函数模式

  • 稳妥对象指没有公共属性,方法也不引用this的对象。适合在安全环境中使用
function Person(name, age, job){
				var o=new Object();				
				// 可以定义私有变量和函数
				var name='lily';
				function otherFunc(){
					conosle.log('ok');
					
				}
				o.sayName=function(){
					console.log(name);					
				}
				
				return o;
			}
			
			var obj=new Person3('lily',25,'后勤');			
			obj.sayName();//lily
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值