class类创造对象
这是es6的一种新方式,class可以看作只是一个语法糖,新的class写法让对象原型的写法更加清晰、更像面向对象编程的语法,下面代码不仅定义了people类,还实现了Coder,和Actor对people 的继承
class People{
constructor(name){
this.name = name
}
eat(){
console.log(`${this.name} eat something`)
}
}
class Coder extends People{
constructor(name,id){
super(name)
this.id=id
}
coding(){
console.log(this.name+'is coding')
}
}
class Actor extends People {
constructor(name,sex){
super(name)
this.sex = sex
}
act(){
console.log(`${this.name} act in the movie is ${this.sex}`)
}
}
const zhangsan = new Coder('张三',9547)
zhangsan.coding()
const li = new Coder('aa',5456)
console.log(li.coding()=== zhangsan.coding())
const huge = new Actor('胡歌','男')
huge.act()
下面这些注意点是对上面的解析可以加强对class的理解:
zhangsan instanceof People
zhangsan instanceof Coder
zhangsan instanceof Object
// 以上判断都是true
typeof Coder
typeof Actor
以上都是function
到控制台输入 Coder.prototype === zhangsan.proto 判断是true
zhangsan.proto 叫隐式原型
Coder.prototype 叫显式原型
每个class都有显示原型
每个实例都有隐式原型
隐式原型的指针指向class对应显示原型
所以原型的执行规则就是先到自身的属性和方法中寻找,找不到则到隐式原型中找
原型链
People.prototype === Coder.prototype.proto //true
字面量创造对象
JS字面量创建方式的优缺点
它省略了构造函数传参初始化这一过程,带来的缺点就是初始化的值都是一致的,(每个实例对象没有自己的特性)
而原型最大的缺点就是它最大的优点,那就是共享。
对象 字面量的ES5的写法
const obj = {
name: 'liqing',
age: 18,
run: function(){
console.log('running')
}
}
对象字面量ES6增强写法
//属性的增强写法
const name= 'liqing'
const age= 18
const obj = {
name,age,
}
// 函数的增强写法
const obj = {
run(){
console.log('it is running')
}
}
工厂模式
这个不多比比,都广为人知了。直接写一遍代码
function createPerson(name, qq) {//构造函数:功能是构造一个对象的函数
//原料
var obj = new Object();
// 当加了new时系统会偷偷的为我们做一些事情:
// var this=new Object();this指向一个空的对象
// 后面 也会 return this;
//加工
obj.name = name;
obj.qq = qq;
//出厂
obj.showName = function () {
alert('My name is ' + this.name);
}
}
var obj1=createPerson('blue','4730');
var obj2=createPerson('张三','5454545');
工厂方式的缺点
// 工厂方式的缺点
// 1,没有new,一般写个对象需要new一个的;
// 2,alert(obj1.showName==obj2.showName);//false
// 要是有100个对象,会浪费系统大量的空间资源,性能低下
//问题1;
var obj1=new createPerson('blue','4730');
var obj2=new createPerson('张三','5454545');
//在创建对象调用函数是在函数前面加上一个new时,是指创建了一个新的对象
//它里面的this就会指向新创建的那个对象
构造函数模式
function Person(name,age,job){
this.name=name
this.age=age
this.job=job
this.sayName = ()=>{
alert(this.name)
}
}
var Person1=new Person('lisi','18','coder')
var Person1=new Person('zhangsan','18','coder')
创建person实例的过程
创建一个新对象–>将构造函数的作用域赋给了this对象–>执行构造函数的代码,为其添加属性和方法–>返回新对象
特点:
没有明显的创建对象
直接将属性和方法赋给了this对象
没有return语句
缺点
如果像上述代码一样创建person实例那么每一个对象都包含一个不同的say那sayname的function实例
alert(person1.sayname== person2.sayname) //false
改进方法
将sayName卸载构造函数外面 ,再构造函数中引用
function Person(name,age,job){
this.name=name
this.age=age
this.job=job
this.sayName = sayName
}
function sayName(){
alert(this.name)
}
原型模式创建对象
这个好像不常用
var Person1=new Person('lisi','18','coder')
function Person(){
}
Person.prototype.name= "zhangsan"
Person.prototype.age=20
Person.prototype.job="coder"
Person.prototype.sayName=()=>{
alert(this.name)
}
var Person1=new Person()
var Person1=new Person()
Person1.name="lisi"
alert(person1.name)//lisi
alert(person2.name)//zhangsan
delete person1.name
alert(person1.name)//zhangsan
组合使用构造函数模式和原型模式
这是一种很常用用的方式:用构造函数模式定义实例属性(不会被共享),而用原型模式用于定义方法和共享的属性,另外这种组合模式还支持向构造函数传递参数
function Person(name,age,gender){
this.name = name;
this.age = age;
this.gender = gender;
this.hobies = ["1","2","3"];
}
Person.prototype = {
sayName : function(){
alert(this.name);
}
}
var person1 = new Person("Stan",0000,"male");
var person2 = new Person("Joe",1111,"female");
person1.colors.push("4");
alert(person1.colors); // 1 2 3 4
alert(person2.colors); // 1 2 3
alert(person1.sayName == person2.sayName); // true
动态原型创造
动态原型模式把所有信息都封装在了构造函数中,而通过在构造函数中初始化原型(仅在必要的情况下),又保持了
同时使用构造函数和原型的优点;换句话说,可以通过检查某个应该存在的方法是否有效,来决定是否需要初始化原型
function Person(name, age, job) {
// 属性
this.name = name;
this.age = age;
this.job = job;
// 方法
if (typeof this.sayName != "function") {
Person.prototype.sayName = function() {
alert(this.name);
}
}
}
var friend = new Person("Mary", 18, "Software Engineer");
friend.sayName();