在ES6 之前生成实例对象通过构造函数和原型链来实现。
function Point(x,y)
{
this.x=x;
this.y=y;
}
Point.prototype.getData=function(){
return {x:this.x,y:this.y}
}
var point=new Point(1,2);//创建实例
point.getData();//{x:1,y:2}
ES6中提供class 创建实例。更类似于java等面向对象编程语法实现。
ES6的类,完全可以看作构造函数的另一种写法。
class Point{
constructor(x,y)
{
this.x=x;
this.y=y;
}
getData(){
return {x:this.x,y:this.y}
}
}
var point=new Point(1,2);
point.getData(); //{x:1,y:2}
typeof Point //function
Point === Point.prototype.constructor //true 由此可见 ES6的类,完全可以看作构造函数的另一种写法。
image.png
类的方法都定义在protoType对象上面,可以将类的方法添加在类的原型上。
//添加单个方法
Point.prototype.toString=function()
{
return {x:this.x,y:this.y}
}
//使用Object.assign 批量添加
Object.assign(Point.prototype,{
add(){
return this.x+this.y;
},
multiplication(){
return (this.x)*(this.y)
}
});
image.png
类内部定义的方法,是不可枚举的
// 只遍历出通过原型添加的方法 ,getData ,constructor方法,没有遍历出。
Object.keys(Point.prototype) //["toString", "add", "multiplication"]
Object.getOwnPropertyNames(Point.prototype) // ["constructor", "getData", "toString", "add", "multiplication"]
constructor 方法
特性:
1.默认方法,生成对象实例时调用。
2.必须存在
3.没有定义,会生成空的构造函数方法。
constructor() {}
类的实例对象
使用new 生成
// 报错
var point = Point(2, 3);
// 正确
var point = new Point(2, 3);
实例的属性除非显式定义在其本身(即定义在this对象上),否则都是定义在原型上(即定义在class上)
如
//point 在上面定义
point.hasOwnProperty('x');//true
point.hasOwnProperty('y');//true
point.hasOwnProperty('getData');//false point 实例不含有getData
point.__proto__.hasOwnProperty('getData');//true
Point.prototype.hasOwnProperty('getData');//true
Point.prototype===point.__proto__//true
Object.assign(point.__proto__,{delete(){
}})//这样也成立,不过一般不这么写。
所有实例共享一个原型对象
var p1 = new Point(2,3);
var p2 = new Point(3,2);
p1.__proto__===p2.__proto__;//true
不存在变量提升
var a=new A();//Uncaught ReferenceError: A is not defined
class A{
}
//普通函数存在变量提升
var b=new B();
function B(){
}
Class 表达式
const M=class {
getName(){
return 1
}
}
var m=new M();
立即执行式的
const n=new class {
constructor(name){
this.name=name
}
getName(){
return this.name
}
}('a');
n.getName();//a
class 中 this的指向
类内部中的this指向类的实例
class F{
constructor(x,y){
this.x=x;
this.y=y;
}
setData(a){
this.x=a;
this.printValue();
}
printValue(){
console.log({x:this.x,y:this.y});
}
}
var f=new F(1,2);
f.setData(12);//会打印出 {x:12,y:2}
//如果将方法分分离
const {setData}=f;
setData(2);//VM132:8 Uncaught TypeError: Cannot set property 'x' of undefined
如果将这个方法提取出来单独使用,this会指向该方法运行时所在的环境,对于做过react 项目的人来说一定有这样的经历,render 中调用的方法需要在构造函数中使用bind绑定,或者采用箭头函数方式,是this指向当前实例
class H{
constructor(x,y){
this.x=x;
this.y=y;
this.setData=this.setData.bind(this);//这种方法就能使方法分离使用
}
setData(a){
this.x=a;
}
//通过箭头函数是this永远指向当前实例
printValue=()=>{
console.log({x:this.x,y:this.y});
}
}
var h=new H(2,4);
const {setData,printValue}=h;
h.setData(12);
printValue();//{x: 12, y: 4}
Class的取值函数(getter)和存值函数(setter)
Class内部可以使用get和set关键字,对某个属性设置存值函数和取值函数,拦截该属性的存取行为。
class MyClass {
rules={
name:{type:'String'},
sex:{default:'男'}
}
props={
}
constructor() {
}
checkedType=(target)=> {
return Object.prototype.toString.call(target).slice(8, -1)
}
// 获得属性
get prop() {
return this.props;
}
//属性赋值
set prop(data) {
for(var i in this.rules)
{
if(data[i])
{
if(this.rules[i].type)//校验传入数据类型
{
if(this.checkedType(data[i])!==this.rules[i].type)
{
data[i]='';
console.log(`${i}类型错误`);
}
}
}
else if(this.rules[i].default)//赋予默认值
{
data[i]=this.rules[i].default;
console.log(`${i}被赋予初始值:${data[i]}`);
}
}
this.props=data
}
}
let inst = new MyClass();
inst.prop = {name:1}; //name类型错误 ,sex被赋予初始值:男
inst.prop;//{name: "", sex: "男"}
网友评论