目录
实例对象与new命令
不同与C++、Java基于类,JS是基于构造函数和原型链
构造函数
JS使用构造函数作为对象的模板,用于实例化对象,特点如下:
- 内部使用this代表要生成的对象实例
- 生成对象的时候,必须使用new命令
new
new的作用是执行构造函数,返回一个实例对象
var Vehicle=function(p){
this.price=p;
}
var v=new Vehicle(10000);
v.price; //10000
原理
- 创建一个空对象,作为要返回的对象
- 将这个空对象的原型[[Prototype]],指向构造函数的prototype属性
- 将空对象赋给this关键字,开始执行函数内部的代码
如果构造函数内部有return语句,而且return返回一个对象,则new命令返回return指定的对象;否则返回this对象
target属性
如果当前函数是new命令调用的,则new.target指向当前函数,否则为undefined
function f(){
console.log(new.target==f);
}
f(); //false
new f(); //true;
注意
如果调用构造函数时,没有使用new,构造函数会变成普通函数,this代表全局对象
var Vehicle=function(){
this.price=1000;
}
var v=Vehicle();
v; //undefined
price; //price成为全局变量
如果使用严格模式,在第一行加上’use strict’,一旦忘记使用new命令,将会报错
this
在JS中,函数可以在不同的运行环境(对象)中执行,使用this能够在函数体内部获得当前的运行环境。this指明函数运行时的对象.
(对比:Java和C++只有类中的函数才使用this关键字)
var f1=function(){
var x=100;
console.log(x);
}
var f2=function(){
var x=100;
console.log(this.x);
}
var x=200;
f1(); //100
f2(); //200
上例中,f1没有加this关键词,输出的是函数作用域内的x;f2加上this关键词,输出的是全局环境的x
用法总结
- 在方法中,this指的是所有者的对象
var Student={ name:'张三'; describe:function(){ console.log('I am '+this.name); } }; var name='李四'; Student.describe(); // '张三' var f=Student.describe; f(); // '李四'
- 在构造函数中,this指的是创建的对象
- 在函数中,this指的是全局对象。在严格模式下,为undefined
function f1(){ return this; } function f2(){ 'use strict'; return this; } f1(); // [Object Window] f2(); // undefined
- 在单独情况下,this指的是对象
绑定this的方法
- call()
- apply()
- bind()
原型对象
函数有一个特定的属性:prototype,指向原型对象。原型对象的属性和方法对于该构造函数的实例对象是共享的。
调用构造函数创建实例对象时,实例对象内部的[[Prototype]]指针就会被赋值为构造函数的原型对象
方法
isPrototypeOf()
A.prototypeOf(B) :A为构造函数;B为实例对象
如果B的[[Prototype]]指向A.prototype,则返回true;否则返回false
getPrototypeOf()
Object.getPrototypeOf(A):A为实例对象
返回A的[[Prototype]]的值
setPrototypeOf()
Object.setPrototypeOf(A,B):A、B为实例对象
让A的[[Prototype]]指向B
原型层级
实例可以读取原型的值,但不能修改。如果添加一个与原型同名的属性,那就会在实例上创建这个属性,遮蔽住原型的属性
获取属性
- for……in……:枚举所有可以遍历的属性,包括实例属性、原型属性。配合Object.hasOwnProperty(obj)可以遍历实例属性
- Object.keys(obj):获取obj可枚举的实例属性,以字符串数组形式返回
- Object.getOwnPropertyNames():获取所有实例属性,以字符串数组形式返回
继承
原型链
继承父类的属性和方法,作为公有属性和方法
子类需要覆盖父类的方法,或者增加父类没有的方法时,必须在原形赋值之后,再添加到原型上
问题:利用原型链继承的属性都是公有的,则不同实例对象的属性值都是一样的
盗用构造函数
利用原型链继承的属性在不同实例对象的属性值都是一样的,可以使用“盗用构造函数”解决
原理:在子类构造函数中调用父类的构造函数
问题:无法继承父类的原型定义的属性和方法。继承的方法无法重用
组合继承
属性使用“盗用构造函数”继承,这样继承的属性是私有的
方法使用“原型链”继承,使得继承的方法可以重用
// 第一步,子类继承父类的实例
function Rectangle() {
Shape.call(this); // 调用父类构造函数
}
// 另一种写法
function Rectangle() {
this.base = Shape;
this.base();
}
// 第二步,子类继承父类的原型
Rectangle.prototype = Object.create(Shape.prototype);
Rectangle.prototype.constructor = Rectangle;
Object相关方法
原型相关
- Object.getPrototypeOf()
- Object.setPrototypeof()
- Object.prototype.isPrototypeof()
属性相关
- Object.getOwnPropertyNames()
- Object.prototype.hasOwnProperty()