原型

  1. 构造函数:function Person(){}
  2. 对象化:var person = new Person();
  3. 原型:Person.prototype  是一个空对象 是祖先

                     Person.prototype.age = 18; 给原型加一个属性

                    var person = new Person();person对象也会继承原型中的age属性


// 原型的增删改查
//构造函数Car
	function Car(){
		// 当实例化对象时,每个对象都会执行Car内的函数。造成代码冗余。
		// 而原型只需执行一次
		this.name = '232'
	}; 


// 构造函数Car里面有原型prototype,他是构造函数实例化对象的公共祖先
	Car.prototype;//为一个空对象
	// 操作原型属性  增删改查
	Car.prototype.age = 18;//增
	Car.prototype.age;//查
	Car.prototype.age = 20;//改
	delete Car.prototype.age;//删

	// 由于原型是个空对象,也可用对象方式添加属性
	Car.prototype = {
		name : '小轿车',
		age : 18,
		color : 'red'
	}

	// 实例化对象  实例化的所有对象都会继承原型中的属性
	var car = new Car();
	console.log(car.age);//18
	console.log(car.name);//232  会就近继承Car构造函数内的属性而不是原型中的属性
	console.log(car.prototype);// undefined 实例化的对象是没有原型的

	console.log(car.constructor);
// prototype里有个constructor属性,为该构造函数 实例化对象也继承该属性,找到自己的构造函数
	function Person(){}
	Car.prototype = {
		constructor : Person//可修改该构造函数 
	}
	console.log(Car.prototype.constructor);

2、__proto__指向对象的原型

function Car(){

}
Car.prototype = {
	name : 'abc'
}
// 实例化对象
var car = new Car();
	car.__proto__;//指向该对象的原型
console.log(car.__proto__);

// 实例化对象  步骤
// 1、在
	// function Car(){
	// 	var this = {//隐性的创建了一个this对象
	// 		__proto__ : Car.prototype //原本就会有一个__proto__属性,值为原型
	// 	};
	// }
// car.__proto__可修改
var obj = {
	age : 18
};
car.__proto__ = obj;//
console.log(car.__proto__);

3、关于__proto__的简单值修改及引用地址修改

// 关于修改原型
function Car(){};
Car.prototype = {
	name : '张三'
}

var car = new Car();
console.log(car.__proto__);//指向Car原型{name:'张三'}

Car.prototype.name = "李四";//修改原型的name值

console.log(car.__proto__);//指向Car原型{name:'李四'}

car.__proto__.name = '朱六';//将原本的原型地址的name属性改为朱六,Car的原型也会变。

console.log(Car.prototype);//指向Car原型{name:'朱六'}
console.log(car.__proto__);//指向Car原型{name:'朱六'}


Car.prototype = {
	name : '王五'
}
console.log(car.__proto__);//指向Car原型{name:'朱六'}
// 虽然原型赋值一个name:王五,但那是给Car的原型指向了另外一个地址,而原本的__proto__还是指向最初的地址。仍旧为李四


// 原理
Car.prototype = {name:"a"};//原型
__proto__ = Car.prototype; //{name:"a"}

//让原型指向另一个地址,但是__proto__指向的仍旧为之前那个{name:"b"}
Car.prototype = {name:'b'};

var obj = {age : 20};
var obj1 = obj;//obj1跟obj指向同一个地方
console.log(obj);//{age:20}
console.log(obj1);//{age:20}
obj1.age = 18;//修改obj1的age属性,就是修改指向的那个地方,obj也会修改
console.log(obj);//{age:18}
console.log(obj1);//{age:18}

obj1 = {age:20};//将obj1指向另一个地址,obj仍旧是之前的地址
console.log(obj1);//20
console.log(obj);//18

4、原型链  (__proto__链接)

// 原型链
// 原型链用__proto__链接

function Grand(){}
Grand.prototype.lastname = '爷爷'; 
var grand = new Grand();

function Father(){
	this.fathername = '爸爸'
}
Father.prototype = grand;//继承对象grand
var father = new Father();


function Son(){
	this.skill = '打游戏'
}
Son.prototype = father;//继承对象father
var son = new Son();

console.log(son.skill);//先找son自身,自身有skill
console.log(son.fathername);//先找son自身,自身没有,通过__proto__找原型,找到father
console.log(son.lastname);//先找son自身,自身没有,通过__proto__找原型,
						// 找到father,father自身没有,通过__proto__找原型grand
console.log(son.toString());//son、father、grand都没有toString方法,
							// 但是原型链中断是Object的原型,里面有该方法

5、原型链上的增删改查

function Father(){
	this.valu = '简单值';
	this.obj = {
		age : 18,
		name : '爸爸'
	}
}
var father = new Father();

function Son(){

}
Son.prototype = father;
son = new Son();
console.log(son.obj.age);
// 增、删、改 无法对原型链上其他函数增加删除属性,
// 修改只能修改引用类型值,不能修改简单类型值
son.obj.age = 20;
son.valu = '修改简单值';//相当于给son自己添加了valu
console.log(son.obj.age);//引用类型值修改成功
console.log(son.valu);//这里是son自己的属性valu
console.log(father.obj.age);//引用类型值改变为20
console.log(father.valu);//father的valu不变


6、创建对象

// 创建构造函数的方法
var obj = {};
var obj1 = new Object();
// {}与new Object()方法一样,__proto__都是指向Object.prototype

var obj2 = Object.create(obj);//Object.create(原型);obj2的__proto__指向括号中原型obj
// 大多数对象的最终都会继承自Object.prototype
// 除了:Object.create(null);以null为原型创建的对象,最终不会是Object
var obj3 = Object.create(null);//没有__proto__

7、内置对象的方法、包装类 Call()

var a = 123;
a.toString();//a调用方法时会先通过包装类,new Number(),然后调用toString

// Number/Array/String/Boolean 都是内置对象,有自己的方法
// 他们的终极原型是Object的原型。
// Object原型里有的方法,可能内置对象中也有
// 比如,Object中有toString,Number中也有。当var a = 123; a.toString()时,调用的是Number中的toString方法。就近原则
// 如果需要选择调用Object中的方法,可以用call()
// 如:
a.toString();//调用Number的方法,转换为字符串"123"
Object.prototype.toString.call(123);//"[object Number]"
Object.prototype.toString.call(true);//"[object Boolean]"

 

8、document.write()


var a = 123;
document.write(a);//页面写出123
var obj = {};
document.write(obj);//页面写出[object object]
var err = Object.create(null);
document.write(err);//报错 

// 因为document.write();会隐式调用toString方法
// Object.create(null)的不在Object原型链上,没有toString方法
// 证明确实是toString()的原因:
err.toString = function(){
	return '就是toString的锅';
}
document.write(err);//页面写出'就是toString的锅'

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值