相关概念:
- 原型
prototype
其实是function对象的一个属性 - 打印出结果来看,会发现它也是一个对象
function Handphone() { }
console.log(Handphone.prototype); // {constructor:f}
-
prototype是定义构造函数构造出的每个对象的公共祖先
所有被该构造函数构造出的对象都可以继承原型上的属性和方法
构造函数中有的属性对象也会有,所以不会再去原型上找
在代码中理解:
function Handphone(color,brand) { this.color = color; this.brand = brand; this.screem = '18:9'; this.system = 'Android'; } Handphone.prototype.rom = '64G'; Handphone.prototype.ram = '6g'; Handphone.prototype.screem = '16:9' var hp1 = new Handphone('red','小米'); var hp2 = new Handphone('black','华为'); console.log(hp1.rom); // 64G console.log(hp1.ram); // 6g console.log(hp1.screem); // 16:9'
-
往往不需要修改的属性和方法,一般会写在原型上,需要配置的写在构造函数内部
-
通过实例化出来的对象,对其继承的原型进行“增删改查”测试:
-
查(对象访问其内部属性):
若是构造函数中没有同时设置一样的属性名和值,其构造函数实例化的对象可以访问其继承的原型上的属性和方法function Test(){} Test.prototype.name = 'prototype'; var test = new Test(); console.log(test.name); // prototype
-
增:
实例化的对象是无法增加其继承的原型上的属性function Test(){} Test.prototype.name = 'prototype'; var test = new Test(); test.num = 1; console.log(Test.prototype,test); // 前者中没有num属性,后者中有
-
改:
实例化的对象是无法修改其继承的原型上的属性 ,最后只会在其自身中增加一个属性
只可以对它重新赋值function Test(){} Test.prototype.name = 'prototype'; var test = new Test(); test.name = 'proto'; console.log(Test.prototype,test);
-
删:
实例化的对象是无法删除其继承的原型上的属性
function Test(){} Test.prototype.name = 'prototype'; var test = new Test(); delete test.name; console.log(Test.prototype,test);
-
constructor 构造器,存在于prototype下
-
constructor (默认) -> 构造函数本身,即,存的是实例化前的东西
function Handphone(color) { this.color = color; } console.log(Handphone.prototype);
-
constructor 可以被修改
function Telephone() {} function Handphone(color) { this.color = color; } Handphone.prototype = { constructor: Telephone, } console.log(Handphone.prototype);
__proto__属性
-
__proto__
是new,实例化对象之后产生的! 是属于每个实例化对象的 -
实质上就是一个装载每个实例化对象的原型的容器;
-
系统内置的属性,所以写法是
__xxx__
,目的是提醒不要乱改function Car(){} Car.prototype.name = 'Benz'; var car = new Car(); console.log(car);
-
因为在实例化之前,构造函数里是没有它的,但是构造函数本身也有一个prototype属性
相当于:实例化后(new)一个对象后,系统在其对象中隐式声明了一个
this
对象,并且默认在里面存了一个__proto__
对象,最后return this
===> 由此可得,__proto__
其实是属于实例化对象的 -
那么,
__proto__
里面存的是什么?🤷♀️以上面的例子为例,存的是实例化后的对象继承的原型Car.prototype,所以原型与构造函数其实是无关的
上面的代码中,实例化后的car可以得到name属性值的原因为:this中没有的属性,系统会自动访问其
__proto__
属性下的原型去寻找,所以它与构造函数无关;再次印证,实质上就是一个装载每个实例化对象的原型的容器; -
这个实例化对象的原型中,
Car.prototype
中存着constructor
,它指向构造函数Car()本身 ,意义之一,在于实例化后告诉你它的构造函数是谁; -
__proto__
是否能被修改?答案是:可以的。 可以试试以下代码:
function Person(){} Person.prototype.name = '张三'; var p1 = { name: '李四' } var person = new Person(); console.log(person.__proto__);
// 此时故意将__proto__修改为p1 function Person(){} Person.prototype.name = '张三'; var p1 = { name: '李四' } var person = new Person(); console.log(person.name); // 张三 person.__proto__ = p1; console.log(person.name); // 李四
-
在实例化后将
prototype
重写的情况:上面的情况,是在实例化后重写的原型prototype,所以和实例化对象的prototype没有关系,这一点是可以印证,prototype是实例化对象的!
如果在实例化前重写的原型prototype,所以后续实例化对象的原型也会改变!
Car.prototype.name = 'Benz'; function Car(){} var car = new Car(); Car.prototype = { name : 'Mazda' } console.log(car.name); // Benz