- 构造函数:function Person(){}
- 对象化:var person = new Person();
- 原型: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的锅'