原型
function CreateUser(name, age, song) {
this.name = name;
this.age = age;
this.song = song;
this.sing = function () {
console.log(`my name is ${this.name}, i'm ${this.age} years old,
i want to sing ${this.song}`);
}
}
// 实例的共有属性
CreateUser.prototype.say = function () {
console.log(`hello javascript ~~, my name is ${this.name}, i'm ${this.age} years old`);
};
var user1 = CreateUser("lulu", 22, "告白气球");
user1.say();
1、所有函数数据类型(普通函数,类),都自带prototype(原型)属性,该属性是对象数据类型的值,浏览器会默认为原型开辟一个新的堆内存
2、原型的堆内存是浏览器默认开辟的,在这个内存中自带constructor属性(只有浏览器给原型开辟的堆内存才有),其属性值就是当前类本身,即:
CreateUser.prototype.constructor === CreateUser
在当前类的prototype上定义的属性都是公有属性
3、所有对象数据类型都自带属性:_proto_,该属性的值是当前对象的所属类原型prototype,IE浏览器禁止使用_proto_属性
1)user1.say(); // 先在实例的私有属性中查找,存在就停止,不存在就通过_proto_找公有属性,若公有私有都有,以私有为准,即:
user1.say === user._proto_.say
2)公有属性中也没有,通过prototype上的_proto_继续查找,一直找到Object.prototype为止
user1.hasOwnProperty === user1._proto_._proto_.hasOwnProperty
![](https://img.haomeiwen.com/i16864957/13eb12f0af64e8d4.png)
批量设置公有属性
1、设置一个新的变量保存原型的地址 不常用
var pro = Object.prototype;
pro.xxx = ...
pro.yyy = ...
2、手动创建一个新的内存给Object.prototype
1)新创建的堆内存会把浏览器默认开辟的内存覆盖掉(是把新内存的地址赋值给prototype),在原内存上创建的自定义属性方法等就不存在了
2)需要继承之前堆内存上有的属性,自己创建的堆内存中不会有constructor,访问该属性时会一直找到Object原型上的constructor,因此还需要手动创建一个constructor,并让他指向所属类
3)为了保护内置类里面的内置方法,浏览器不允许重新创建一个堆内存覆盖原有原型的,要基于原有内置类增加方法,可采用方法1,自己在原型上增加的方法可以用for in 遍历到,只有浏览器内置的一些比较重要的原型上的方法用for in 才不会遍历到
// 保存原来的
var pro = Fn.prototype;
// 开辟新的
Fn.prototype = {
// 创建constructor
constructor = Fn,
getX: function(){},
getY: function(){},
.....
recover: function(){
// 把原来的复制到新的里面 先判断以防止公有方法重写
for(var key in pro){
if(key in this){
this["my"+key] = this[key];
}
this[key] = pro[key];
}
}
};
this指向
- 1)自执行函数中的this永远是window
- 2)给元素绑定触发事件,当事件触发的时候,方法中的this就是该元素
- 3)方法名执行,前面若有点(.),点(.)前面是谁this就是谁,没有点(.),this就是window
- 4)实例是构造函数中的this
- 5)使用call和apply可以任意修改this指向
原型继承
让子类的原型等于父类的一个实例,这样子类就可以继承父类中的属性和方法
JS中存在重写,因此子类可以修改父类原型中的属性和方法导致父类的其他实例也受影响
![](https://img.haomeiwen.com/i16864957/2346a47029193c84.png)
原型中的Function
每一个函数(类)既是函数数据类型,也是一个对象数据类型(函数的双面性)
函数执行时可以形成私有作用域,同时也开辟了一个堆内存,存储代码字符串,自带一些属性如prototype,_proto_
![](https://img.haomeiwen.com/i16864957/fcf1e47db61f5b70.png)
其他类的原型都是"object",typeof Function.prototype = "function",对应一个空函数,但操作都一样
Object.prototype(); // Error:Object.prototype is not a function
Function.prototype(); // 可以执行
网友评论