原型链
**定义:**按照JS引擎的分析方式,在访问一个实例的属性的时候,现在实例本身中找,如果没找到就去它的原型中找,还没找到就再往上找,直到找到。这就是原型链。
- 实例的_protpo_指向的是原型对象。
- 实例的构造函数的prototype也是指向的原型对象。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BmXttn5y-1610412275756)(C:\Users\geqilin\AppData\Roaming\Typora\typora-user-images\1597286397572.png)]
4.类与继承
1.类的定义
//类的声明
var Animal = function () {
this.name = 'Animal';
};
//第二种,Parent2为类的构造函数。
function Parent2 () {
this.name = 'parent2';
this.play = [1, 2, 3];
}
obj=new Parent2();
//ES6中类的声明
class Animal2 {
constructor () {
this.name = 'Animal2';
}
}
2.原型的属性和对象的属性
在实例的原型上添加一个方法,这个原型的所有实例便都有了这个方法。
1)原型属性相当于类属性,所有实例共享。
function Parent3 () {
this.name = 'parent3';
this.play = [1, 2, 3];
};
var obj=new Parent3();
obj.prototype.play=[1,2,3,4,5];
//obj.play对象的属性
console.log(obj.play);//(3) [1, 2, 3]
//obj.__proto__.play访问原型的属性
console.log(obj.__proto__.play);//(5) [1, 2, 3, 4, 5]
2)只有创建一个实例对象才能访问到函数的原型属性。
function a2(){this.name="lisi"}
undefined
a2
ƒ a2(){this.name="lisi"}
a2.prototype.a=2;
2
a2.a;
undefined
a2.__proto__;
ƒ () { [native code] }
var b=new a2();
undefined
b;
a2 {name: "lisi"}
name: "lisi"
__proto__:
a: 2
constructor: ƒ a2()
__proto__: Object
3.JS中的call()方法和apply()方法
作用:
都是在特定的作用域中调用函数,等于设置函数体内this对象的值,以扩充函数赖以运行的作用域。
一般来说,this总是指向调用某个方法的对象,但是使用call()和apply()方法时,就会改变this的指向
语法:
如果不传参数则使用全局对象;
函数名.call(’想将目标函数this改成的值‘);
函数名.apply(’想将目标函数this改成的值‘);
相同点:二者实现的功能相同;
不同点:
add第二个参数为可变长数组,apply第二个参数为数组。
function add(c,d){
return this.a + this.b + c + d;
}
var s = {a:1, b:2};
console.log(add.call(s,3,4)); // 1+2+3+4 = 10
console.log(add.apply(s,[5,6])); // 1+2+5+6 = 14
4.Object.create
语法:
Object.create(proto[, propertiesObject])
参数
-
proto
新创建对象的原型对象。
-
propertiesObject
可选。如果没有指定为
undefined
,则是要添加到新创建对象的不可枚举(默认)属性(即其自身定义的属性,而不是其原型链上的枚举属性)对象的属性描述符以及相应的属性名称。这些属性对应Object.defineProperties()
的第二个参数。
返回值:
一个新对象,带着指定的原型对象和属性。
注意:
如果propertiesObject
参数是 null
或非原始包装对象,则抛出一个 TypeError
异常。
function MyClass() {
SuperClass.call(this);
OtherSuperClass.call(this);
}
// 继承一个类,第二个参数创建一个可写的,可枚举的,可配置的属性p
MyClass.prototype = Object.create(SuperClass.prototype, {
p: {
value: 42,
writable: true,
enumerable: true,
configurable: true
}
// 混合其它
Object.assign(MyClass.prototype, OtherSuperClass.prototype);
// 重新指定constructor
MyClass.prototype.constructor = MyClass;
MyClass.prototype.myMethod = function() {
// do a thing
};
Object.assign 会把 OtherSuperClass
原型上的函数拷贝到 MyClass
原型上,使 MyClass 的所有实例都可用 OtherSuperClass 的方法。
5.继承
// Shape - 父类(superclass)
function Shape() {
this.x = 0;
this.y = 0;
}
// 父类的方法
Shape.prototype.move = function(x, y) {
this.x += x;
this.y += y;
console.info('Shape moved.');
};
// Rectangle - 子类(subclass)
function Rectangle() {
Shape.call(this); // call super constructor.继承父类的非原型属性(普通属性)
}
// 子类续承父类
Rectangle.prototype = Object.create(Shape.prototype);//获取父类原型属性
//上一步继承了父类的原型对象所以构造器为父类的构造器,因此需要将构造器设置为自己的。
Rectangle.prototype.constructor = Rectangle;
var rect = new Rectangle();
console.log('Is rect an instance of Rectangle?',
rect instanceof Rectangle); // true
console.log('Is rect an instance of Shape?',
rect instanceof Shape); // true
rect.move(1, 1); // Outputs, 'Shape moved.'