构造函数&&原型(包装类(包装对象)、工厂模式&&构造函数、原型)

对象的创建方式

var obj = {}叫做对象字面量或者叫做对象直接量

那么如何给当前对象添加一个属性和方法呢??

 var obj = {};//对象字面量/对象直接量
	   obj.name = "huasheng";//添加属性
	   obj.sayName = function(){//添加方法,方法是个函数
	      console.log(this.name);
	   };

在这里插入图片描述
当前obj中有一个name属性和一个sayName的方法,当obj里面的sayName方法一执行就把sayName的名字打印出来

包装类(包装对象)

对象是有属性和方法的,只有对象有属性和方法而原始值是没有属性和方法的。

 var str = "huasheng";
	   console.log(str.length);
	   console.log(str.indexOf("u"));

在这里插入图片描述
在JS中只有对象才能够属性和方法,这句话无安全是没有问题的,之所以我们能看到原始值有属性和方法是因为JS系统自动的给这些原始值添加了包装对象

new String()

 var str = "huasheng";
	   console.log(str.length);
	   console.log(str.indexOf("u"));

字符串加上.JS系统会给你加上new String(str)这句话的,把你的str里面的字符串给你传进去,把你的字符串"huasheng"传进去包装成一个字符串对象,然后包装成一个字符串对象之后他就有属性了。

var str = "huasheng";
	   console.log(new String(str));
	   console.log(typeof new String(str));

他会把你str属性传到new String里面然后在包装成一个字符串对象,在使用里面的方法。
在这里插入图片描述
第一个是包装完的字符串对象,第二个用typeof检查出来的结果他是一个object表示一个对象

var str = "huasheng";
	   console.log(new String(str).length);

原始值他是不能使用方法和属性的,JS引擎只能把原始值包装成一个对象在使用,如现在查询str里面的length的长度,他是调用new String的包装对象包装成一个字符串对象在使用。
在这里插入图片描述
new Number(num)

 var num = 2;
		console.log(num.toString());

在这里插入图片描述
那么num是原始值,那为什么num上面有一个to String()函数呢,其实是JS引擎在你调用to String()函数的时候给你包装成数字对象,调用new Number()函数把num给传进去变成一个数字对象在使用to String方法

var num = 2;
		console.log(new Number(num));
		console.log(new Number(num).toString());

在这里插入图片描述
第一个是把num当做参数传进去通过new Number()函数包装成一个数字对象在使用,第二个是包装完的数字对象在调用to String方法转换成字符串是"2"

var num = 2;
		console.log( typeof new Number(num));

在这里插入图片描述
typeof一下检查出来的结果他是一个object表示一个对象

new Boolean(bool)

var bool = false;
	   console.log(bool.toString());

在这里插入图片描述
那么bool是原始值,那为什么bool上面有一个to String()函数呢,是JS引擎把这个bool偷偷地包装成了一个布尔对象,通过new函数启动了Boolean函数把bool传进去包装成一个布尔对象

var bool = false;
	   console.log(new Boolean(bool));
	   console.log(typeof new Boolean(bool));

在这里插入图片描述
第一个是把bool当做参数传进去通过new函数启动了Boolean函数包装成一个布尔对象在使用,第二个是包装完的布尔对象用typeof检查是一个object类型表示一个对象

总结

在JS中只有对象才能够属性和方法

但是在JS中存在3个包装类

  1. new Number(num) --> 把原始值num变成数字对象
  2. new Boolean(bool) --> 把原始值bool变成布尔对象
  3. new String(str) --> 把原始值str变成字符串对象

都是通过new函数启动的NumberBooleanString函数的

在我们日常写JS代码中,根本不用包装成数字对象,包装成字符串对象,包装成布尔对象,这个只是解释为什么原始值可以有属性和方法。(只要知道JS中有包装类这个概念就可以了)

练习

 var str = 'huasheng';
		str = str + 3; //"huasheng"+3 --> "huasheng3"
		var result = typeof str; //"string"
		if (result.length === 6) {//length长度等于6走一下代码
			result.len = '返回的结果是string';//new String(result)包装成一个字符串对象
			//但是这个字符串对象在下一个是被销毁了根本没什么用
		}
		console.log(result.len);  //undefined
		console.log(result.length);//6
		//result.length这个length属性是不能销毁的,length是一直存在字符串身上的。

src.length这个length属性是不能销毁的是默认存在的,length是一直存在字符串身上的。

工厂模式&&构造函数

工厂模式

var person1 = {}; 
    person1.name = 'huasheng';
    person1.age = 28;
    person1.sayName = function(){
        console.log(this.name)
    }
    
    var person2 = {}; 
    person2.name = '花生';
    person2.age = 26;
    person2.sayName = function(){
        console.log(this.name)
    }
    
    
    var person3 = {}; 
    person3.name = '牛肝菌';
    person3.age = 25;
    person3.sayName = function(){
        console.log(this.name)
    }
    
    var person4 = {}; 
    person4.name = '一念';
    person4.age = 18;
    person4.sayName = function(){
        console.log(this.name)
    }

用对象字面量的形式创建4个有相同属性的代码

在JS中会使用到许多的对象如上:

当前代码是有很多的,是有很多重复的,当我们要定义一些人,这些人都有相同的属性的时候,这会造成我们当前的代码重复量太多了

其实是可以吧这些重复的代码封装在一个函数中的

用函数的形式创建有相同属性的代码

function person(name,age){  //工厂模式
        var obj = {};         //原料
        obj.name = name;      //加工
        obj.age = age;
        obj.sayName = function(){
            console.log(this.name)
        }
        return obj;             //出厂
    }
	var person1 = person('花生',28);
    var person2 = person('huasheng',26);
    var person3 = person('牛肝菌',25);
    var person4 = person('一念',18);
    function car(width,height,brand){  //工厂模式
        var obj = {};         //原料
        obj.width = width;      //加工
        obj.height = height;
        obj.brand = brand;
        return obj;             //出厂
    }

    var car1 = car(250,200,'大众');
    var car2 = car(220,180,'奔驰')
    function phone(brand,color,price){  //工厂模式
        var obj = {};         //原料
        obj.brand = brand;      //加工
        obj.color = color;
        obj.price = price;
        return obj;             //出厂
    }

    var phone1 = phone('iphone','黑色',5000);
    var phone2 = phone('华为','白色',6000);

理由这种机制就可以简化我们的代码了。这种可以理解为是工厂模式

其实工厂模式他也是有弊端的,就在上面用工厂模式整的3块代码这样的代码重复量太累不好,那么怎么解决这种弊端呢

构造工厂模式(构造函数)

function Person(name, age) {  //构造工厂模式
        this.name = name;
		this.age = age;
		this.sayName = function () {
			console.log(this.name)
		}
	}
	var person1 = new Person("花生",28);

其实new关键词是一种启动函数的方式,启动的时候会让函数内部发生变化

new关键词的作用

  1. 生成一个空对象 {}
  2. this 指向 生成的空对象{}
  3. return 会默认的把this抛出
  4. 以上三点都是隐式的

通过new关键词启动的函数,这个函数的名字必须首字母大写Person

一旦在JS代码中看见一个单词的首字母大写的时候,那么这个单词就是构造函数(必须这样写JS代码的要求)

普通函数和构造函数没有任何的区别,都是可以通过new函数启动。一旦一个函数通过new关键词启动了那么这个函数就是构造函数。

function Person(name, age) {  //构造工厂模式
        this.name = name;
		this.age = age;
		this.sayName = function () {
			console.log(this.name)
		}
		// return 2;//person1不会接受用return抛出的原始值
		return [1,2,3];//person1会接受引用值抛出的结果
	}
	var person1 = new Person("花生",28);

但是如果人为的显式return

  • 则原始值不会被抛出
  • 引用值会被抛出

原型

创建一个构造函数

function Person(name,age){
	    this.name = name;//特性
		this.age = age;//特性
		this.sayName = function(){//共性
			 console.log(this.name);
		}
}
var person1 = new Person("花生",28);
var person2 = new Person("huasheng",16);

在上面的代码中,name名字和age年龄是他们的特性也是(私有属性),sayName是共性(是共同属性)。

那么他们的共同属性sayName是不是他们的共同属性

 console.log(person1.sayName === person2.sayName);

在这里插入图片描述发现做全等比较的时候是false不全等

说明了person1person2的函数并不是一个函数,其实这是JS给person1person2这两个函数分别开辟了两个空间的。

那么怎么把这两个函数的sayName属性放在一个空间里呢??

        function Person(name,age){//工厂
			 this.name = name;
			 this.age = age;
		 }
		 Person.prototype.sayName = function (){//原始的模子
				console.log(this.name);
		 }
		 var person1 = new Person("花生",28);//出厂
		 var person2 = new Person("huasheng",16);

这会在给person1函数中的sayName属性和person2函数中的sayName属性作比较

console.log(person1.sayName === person2.sayName);

在这里插入图片描述
在这里插入图片描述
结果是true,发现person1函数中的sayName属性和person2函数中的sayName属性并不是在person函数中的。

Person.prototype原型原始模型是一个对象

那为什么person1 person2 中有sayName方法并且是全等呢

那为什么person1 person2 中有sayName方法

通过new关键词启动了Person函数然后生成了person1person2Person函数他是一个工厂是可以生成函数的,而Person.prototype 是存储着原始的模型,person1 person2 都是通过这个原始模型往下做出来的,做出来的东西都保留着这个原始模型。

那为什么person1 person2 中有sayName方法是因为原始的模型上有sayName的方法,而person1 person2都是这个原始模型做出来的东西自然而然就有保留sayName这个方法了

那为什么person1person2做比较时是全等呢??

是因为sayName的从原始模型出来的而person1person2是这个原始模型所出来的产品都保留这个原始的模型所以是true

通过new关键词启动的函数时,生成一个空对象

其实这个对象不完全是空的他还是一个对象的。

他里面还是有东西的那就是{__proto__}是JS内置的属性(可看可改)

只要是对象就有{__proto__}这个属性是指一个属性的原始模型

他指向的是你用哪个函数启动的原始模型{__proto__:Person.prototype}

完整的Person是如下

    {
       __proto__:Person.prototype,
       name:'花生',
       age:28
     }

在这里插入图片描述
为什么person1.sayName我们可以查到他是一个函数的呢??

person1.sayName他会往__proto__这个属性里去找他指向的是Person.prototype,而Person.prototype他上面是有sayName这个属性的。当一个函数里没有想要找的属性就去__proto__里面去找,有就有没有则就没有

他们的连接点在于每个对象上面都有__proto__这个属性是JS内置的属性他指向的是原始模型

对象查找属性的规则

  1. 先查找自身上面有没有指定属性
  2. 如果没有在自身上找到指定属性 ,那就从__proto__属性中查找有没有指定属性

练习题目

第一题

 function Person(){
        /*
        *   {
        *       __proto__:Person.prototype,
        *   }
        * */
    }
    
    /*
    *   Person.prototype:{
    *       name:'oldsix'
    *   }
    * */
    Person.prototype.name = 'heaven';
    var person1 = new Person();
    Person.prototype.name = 'oldsix';
    console.log(person1.name);

第二题

   function Person(){
      /*
     *   {
     *       __proto__:Person.prototype  (1)
      *   }
      * */
    }
    /*
    *   Person.prototype={  (1)
    *       name:'heaven'
    *   }
    *
    *    Person.prototype={  (2)
    *       name:'oldsix'
    *   }
    * */
    Person.prototype.name = 'heaven';
    var person1 = new Person();
    Person.prototype = {
        name:'oldsix'
    }
    console.log(person1.name);

第三题

   function Person(){
        /*
        *   {
        *       __proto__:Person.prototype(2)
        *   }
        * */
    }
    /*
    *   Person.prototype={ (1)
    *       name:'heaven'
    *   }
    *
    *   Person.prototype={ (2)
    *       name:'oldsix'
    *   }
    *
    * */
    Person.prototype.name = 'heaven';
    Person.prototype = {
        name:'oldsix'
    }
    var person1 = new Person();
    console.log(person1.name);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值