JavaScript-04

新特性:

设置原型:

前一篇有一点没有说的是:__proto__并不是ECMAScript标准,尽管有很多浏览器实现了这个属性。

ES5的时候引入了Object.create():

var a = {a: 1};     // a ---> Object.prototype ---> null
var b = Object.create(a);    // b ---> a ---> Object.prototype ---> null

这个在上一篇见过,但是理解不够透彻,其实就是ES提供的设置原型的方法。

ES标准在ES6的时候又引入了两个方法来做这件事儿。

Object.getPrototypeOf(someObject)  === someObject.__proto__

//另一个就是设置原型
son.__proto__ = Parent.prototype;    //非标准
Object.setPrototypeOf(son, Parent.prototype);

讲真的,这个标准的写法比__proto__弱多了,简直是强行增加思维难度。

class语法糖:class constructor extends super static  

class Person{
	constructor(name){
		this.name = name;
	}

	run(){
		console.log(this.name + ' running');
	}
}

class Man extends Person{
	constructor(name, sex){
		super(name);
		this.sex = sex;
	}

	mySex(){
		console.log(this.name + ' is ' + this.sex);
	}

	static Version(){    //用于静态方法
		console.log('v1.0');
	}
}


var m1 = new Man('lisi','male');
var m2 = new Man('wangwu', 'female');

原型链:续

昨天看了知道了原型链概念,但是对于__proto__和prototype还是模模糊糊的。分析了一番之后得出结论:

  1. __proto__(对象都有的) ,指向当前对象的原型对象,类比到class机制下,就是指向当前类的父类
  2. prototype(function都有的对象),创建函数的同时,会生成一个原型对象,类比到构造方法和类的关系

有了上面的两条结论,再去理解原型链就很容易了。关键是和一般的面向对象做对比来。

function Person(props){
	this.name = props.name || 'noname';
}

Person.prototype.run = function(){	//相当于类方法
	console.log(this.name + ' running');
}

function createPerson(props){
	return new Person(props || {});
}

var p = createPerson();

以昨晚的代码为例,我们很容易写出原型链:

p.__proto__ === Person.prototype //p继承Person构造方法对应的原型也就是Person.prototype
Person.prototype.__proto__ === Object.prototype    //同理
Object.prototype.__proto__ === null    //原型链终点

理解的难点在于要清楚,JS不用创建类,也没法创建类。使用原型的概念去替代类。然后这个原型也不需要手动去创建,当你写一个方法的时候,这个方法就会具有一个prototype对象,这个对象就是原型。

Person.prototype.constructor === Person    //原型的构造函数 自动绑定到Person

到这里原型链基本就没什么秘密了。接下来看在这种模式下,继承如何实现呢。

继承:

1. 继承第一点,肯定是要获取父类的属性和方法,做法如下:

function Man(props){
	Person.call(this, props);	//这一步相当于复用了Person的代码
	this.sex = props.sex || 'male';
}

就是把this绑定到父类用apply或call调用即可。

2. 把原型链设置正确:

Man.prototype.__proto__ = Person.prototype    //非标准
Man.prototype = Object.create(Person.prototype);           //ES5标准
Object.setPrototypeOf(Man.prototype, Person.prototype);    //ES6标准

当然,在ES6后又提出了一套class语法糖,原理还是一样的原理,不过有了语法糖写起来就很符合习惯。

继承还有一种方法,利用一个架桥函数,不过说实话这种方法,在ES5 ES6之后出来之后,意义不大。做法如下:

function F(){}	//空函数
F.prototype = Person.prototype;	//把这个空函数原型对象设为父类

Man.prototype = new F();	//子类的原型对象设为F的实例
Man.prototype.constructor = Man;	//修改子类的构造函数

猜你喜欢

转载自blog.csdn.net/qq_21294095/article/details/86636428