JS高级学习路线——面向对象进阶

时间:2022-11-15 22:57:56

构造函数进阶

使用构造函数 创建对象

用于创建对象 其除了是一个函数之外,我们又称之为构造对象的函数 - 简称构造函数

    function Product(name,description){
//属性
this.name=name;
// 属性
this.description = description
//方法 又称方法属性 万物皆属性
this.buy=function(){
alert('buy')
}
} //会拷贝一份
var p1 = new Product()
var p2 = new Product()
  //实例p1,p2的构造函数是谁
console.log(p1.constructor)
console.log(p2.constructor)

如何判断某个实例是否是根据某个构造函数创建的
if(p1 instanceof Product){
alert('true')
}

存在的问题
每个实例的name,描述确实不一样,需要单独的空间存储,但是buy方法是所有实例都一样的

为了避免内存浪费,所以出现了原型帮助我们解决这个问题

原型对象 不管你实例化多少次,都只生成一次

四种创建方式

1.传参形式

2.默认值

3.动态添加形式

4.混合模式

函数声明和函数表达式的区别


搭积木开发 -- 代码可读性极高

 //产品对象
/*类 -- 抽象对象*/
function Product(name,price) {
/*属性 行为 可以为空或者给默认值*/
this.name=name
this.price=0;
/*我们的需求:自动计算打折后的价格*/
/*形象的理解:包装*/
Object.defineProperty(this, "price", {
get: function () {return price*0.9;},
set: function (value) {
/*大概普通产品的价格都在0--1万*/
if(value>10000)
{
alert('产品价格必须在0--1万之间');
}else{
price = value;
}
}
});
} //定义对象的两种方式
Product.prototype={
getPrice:function() {
return this.price
},
addToCart:function(){
alert('将物品添加到购物车')
}
} Product.prototype.buy=function(){}
Product.prototype.addToCart=function(){} /*获取元素*/
var btn = document.getElementById('btn')
var name = document.getElementById('pname') window.onload=function() {
/*实例化 -- 实例 -- 具体*/
//如何使用
//对象的使用必须先实例化,对象定义好之后,都是抽象的,必须实例化成具体
var iphone = new Product() /*给对象的赋值赋值,也可以新增属性*/
iphone.name='iphone7'
iphone.price=6000 /*绑定元素*/
/*通过点语法访问对象中的属性或者方法*/
name.innerHTML=iphone.name
price.innerHTML=iphone.price /*绑定事件*/
btn.onclick = function(){
iphone.addToCart()
}
}

  

对象属性进阶1 get set权限

产品对象

1.对象内如何使用对象的属性和方法:this

2.对象外如何使用:先实例化,后用点语法

类 -- 抽象对象

    function Product(name,price) {
/*属性 行为 可以为空或者给默认值*/
this.name=name
this.price=0;
this.description = '';
this.zhekou = ''
this.sales = ''
/*我们的需求:自动计算打折后的价格*/
/*形象的理解:包装*/
Object.defineProperty(this, "price", {
get: function () {return price*0.9;},
set: function (value) {
/*大概普通产品的价格都在0--1万*/
if(value>10000)
{
alert('产品价格必须在0--1万之间');
}else{
price = value;
}
}
});
}

  get set 日期 拓展性知识

Object.defineProperty(this, "produceDate", {
get: function () {
return dateFormat(produceDate,'yyyy-MM-dd');
},
set: function (value) {
produceDate = value;
}
});
function dateFormat(date,format) {
var o = {
"M+" : date.getMonth()+1, //month
"d+" : date.getDate(), //day
"h+" : date.getHours(), //hour
"m+" : date.getMinutes(), //minute
"s+" : date.getSeconds(), //second
"q+" : Math.floor((date.getMonth()+3)/3), //quarter
"S" : date.getMilliseconds() //millisecond
}
if(/(y+)/.test(format)) format=format.replace(RegExp.$1,
(date.getFullYear()+"").substr(4- RegExp.$1.length));
for(var k in o)if(new RegExp("("+ k +")").test(format))
format = format.replace(RegExp.$1,
RegExp.$1.length==1? o[k] :
("00"+ o[k]).substr((""+ o[k]).length));
return format;
}

  权限的设置——可读

/*我们的需求:自动计算打折后的价格*/
Object.defineProperty(this, "price", {
value:5000000,
writable: t,
});

  


对象属性进阶2 公有私有属性

对象构造函数

    // 私有属性好处: 安全 就类似闭包中的函数一样 减少污染
function Person(name) {
//私有属性,只能在对象构造函数内部使用
var className = "用户对象";
//公有属性,在对象实例化后调用
this.name = name;
//私有方法
var privateFunction = function () {
alert(this.name);
}
//公有方法
this.publicFunction = function () {
alert(this.name); //公有属性
alert(className); //正确 直接通过变量名访问
alert(this.className); //undefined 错误 不能这样访问
}
//公有属性
alert(className);
//正确 直接通过变量名访问
alert(this.className); //undefined 错误 不能这样访问
}

什么是公有属性:
使用象的人可以访问到对象内部的某个属性

init函数的引入

Product.prototype={
/*初始化函数的引入*/
/*我们将开发某个功能的初始化的工作都放在一起函数里面,用户只需要只要这一个工具就可以了*/
init:function(){
this.bindDOM()
this.bindEvents() },
bindDOM:function(){},
bindEvents:function(){}
}

私有成员的引入

    //产品对象
/*类 -- 抽象对象*/
function Product(name,price) {
/*属性 行为 可以为空或者给默认值*/
this.name=name
this.price=1000;
this.description = '';
this.produceDate
/*我们的需求:自动计算打折后的价格*/
Object.defineProperty(this, "price", {
value:5000000,
writable: false,
});
var that = this;//改变this指向
function bindDOM(){
/*获取元素*/
var btn = document.getElementById('btn')
var name = document.getElementById('pname')
/*绑定元素*/
/*通过点语法访问对象中的属性或者方法*/
name.innerHTML=that.name
price.innerHTML=that.price
}
function bindEvents(){
var btn = document.getElementById('btn')
/*绑定事件*/
btn.onclick = function(){
that.addToCart()
}
}
this.init = function(){
/*访问方式:不加this*/
bindDOM()
bindEvents()
}
}
//定义对象的两种方式
Product.prototype={
getPrice:function() {
return this.price
},
addToCart:function(){
alert('将物品添加到购物车')
}
} 

config

        var that = this;
//定义一个变量 :这个变量可以被对象中所有的属性访问到。。。。
/*避免重复,减少内存*/
/*统一管理*/
this.config = {
btnConfirm: document.getElementById('btn'),
btnBuy: document.getElementById('btn'),
sum : 1000,
des : document.getElementById('pdes'),
youhuijia : document.getElementById('pyouhui'),
zhekou : document.getElementById('pzhekou')
}
function bindDOM(){
that.config.name.innerHTML=that.name
}

对象实例进阶

数据类型的复习

//数值型
var num1 = 1;
//字符串型
var num2 ='2333fgfgfggggggggggggggggggggg';
//布尔型
var num3 =false;
//对象型
var num4 = document.getElementById('mydiv');
//未定义
var num5; 

call

    console.log(toString.call(123)) //[object Number]

    var num = 123;

    console.log(num.toString())  //toString() 方法可把一个逻辑值转换为字符串,并返回结果

数据类型检测进阶

数据类型判断 - typeof

    console.log(typeof undefined)//'undefined'
console.log(typeof null) // well-known bug
console.log(typeof true) //'boolean'
console.log(typeof 123) //'number'
console.log(typeof "abc") //'string'
console.log(typeof function() {}) //'function'
var arr=[];
console.log(typeof {}) //'object'
console.log(typeof arr)//'object'
console.log(typeof unknownVariable) //'undefined'
// 在使用 typeof 运算符时采用引用类型存储值会出现一个问题,
// 无论引用的是什么类型的对象,它都返回 "object"

数据类型判断 - toString.call
通用但很繁琐的方法: prototype

    console.log(toString.call(123))          //[object Number]
console.log(toString.call('123')) //[object String]
console.log(toString.call(undefined)) //[object Undefined]
console.log(toString.call(true)) //[object Boolean]
console.log(toString.call({})) //[object Object]
console.log(toString.call([])) //[object Array]
console.log(toString.call(function(){})) //[object Function] console.log(Object.prototype.toString.call(str) === '[object String]') //-------> true;
console.log(Object.prototype.toString.call(num) === '[object Number]') //-------> true;
console.log(Object.prototype.toString.call(arr) === '[object Array]') //-------> true;
console.log(Object.prototype.toString.call(date) === '[object Date]') //-------> true;
console.log(Object.prototype.toString.call(fn) === '[object Function]') //-------> true;

数据类型判断 - instanceof

   //    判断已知对象类型的方法: instanceof
console.log(arr instanceof Array) //---------------> true
console.log(date instanceof Date) //---------------> true
console.log(fn instanceof Function) //------------> true
//alert(f instanceof function) //------------> false
//注意:instanceof 后面一定要是对象类型,并且大小写不能错,该方法适合一些条件选择或分支。

数据类型判断 - 根据对象的constructor判断: constructor

 //    根据对象的constructor判断: constructor
var arr=[];
console.log('数据类型判断 - constructor')
console.log(arr.constructor === Array) //----------> true
console.log(date.constructor === Date) //-----------> true
console.log(fn.constructor === Function) //-------> true

数据类型判断 函数封装

判断变量是不是数值型

    function isNumber0(val){
return typeof val === 'number';
} // 但有些情况就不行,比如:
// 1 var a;
// 2 alert(isNumber(parseInt(a)));
// 但实际上变量a是NaN,它是不能用于数值运算的。
// 所以上面的函数可以修改为: function isNumber(val){
return typeof val === 'number' && isFinite(val);
} // 顺便介绍一下JavaScript isFinite() 函数,isFinite() 函数用于检查其参数是否是无穷大,
// 如果 number 是有限数字(或可转换为有限数字),
// 那么返回 true。否则,如果 number 是 NaN(非数字),或者是正、负无穷大的数,则返回 false。

    判断变量是不是布尔类型

 function isBooleanType(val) {
return typeof val ==="boolean";
}

  判断变量是不是字符串类型

 function isStringType(val) {
return typeof val === "string";
}

 判断变量是不是Undefined

 function isUndefined(val) {
return typeof val === "undefined";
} var a;//a是undefined
var s = "strType";
alert("变量a是Undefined的判断结果是:"+isUndefined(a));
alert("变量s是Undefined的判断结果是:"+isUndefined(s));

判断变量是不是对象

function isObj(str){
if(str === null || typeof str === 'undefined'){
return false;
}
return typeof str === 'object';
}
var a;
var b = null;
var c = "str";
var d = {};
var e = new Object();
alert("变量a是Object类型的判断结果是:"+isObj(a));//false
alert("变量b是Object类型的判断结果是:"+isObj(b));//false
alert("变量c是Object类型的判断结果是:"+isObj(c));//false
alert("变量d是Object类型的判断结果是:"+isObj(d));//true
alert("变量e是Object类型的判断结果是:"+isObj(e));//true

判断变量是不是null

function isNull(val){
return val === null;
}
/*测试变量*/
var a;
var b = null;
var c = "str";
//弹出运行结果
alert("变量a是null的判断结果是:"+isNull(a));//false
alert("变量b是null类型的判断结果是:"+isNull(b));//true
alert("变量c是null类型的判断结果是:"+isNull(c));//false

判断变量是不是数组

//数组类型不可用typeof来判断。因为当变量是数组类型是,typeof会返回object。
//方法1
function isArray1(arr) {
return Object.prototype.toString.call(arr) === '[object Array]';
}
//方法2
function isArray2(arr) {
if(arr === null || typeof arr === 'undefined'){
return false;
}
return arr.constructor === Array;
}

Jquery判断数据类型

//    jQuery提供一系列工具方法,用来判断数据类型,以弥补JavaScript原生的typeof运算符的不足。
// 以下方法对参数进行判断,返回一个布尔值。 // jQuery.isArray():是否为数组。
// jQuery.isEmptyObject():是否为空对象(不含可枚举的属性)。
// jQuery.isFunction():是否为函数。
// jQuery.isNumeric():是否为数字。
// jQuery.isPlainObject():是否为使用“{}”或“new Object”生成的对象,而不是浏览器原生提供的对象。
// jQuery.isWindow():是否为window对象。
// jQuery.isXMLDoc():判断一个DOM节点是否处于XML文档之中。

原型对象的进阶

属性屏蔽理论

	function Product() {
//属性
this.name = '神仙';
// 属性
this.description = ''
this.buy = function() {
alert('构造函数对象')
}
}
Product.prototype = {
name: '魔鬼',
buy: function() {
alert('原型对象')
}
}
var product = new Product()
console.log(product.name)
delete product.name
product.name = '魔鬼2'
console.log(product.name)
/*原型属性屏蔽理论 -- 乌云蔽日*/
console.log(product.buy())
/*清除乌云*/
delete product.buy
//console.log(product.name)
console.log(product.buy())
/*被屏蔽之后如何获取 */
//console.log(Product.prototype.buy())

hasOwnProperty

        //hasOwnProperty : 看是不是对象自身下面的属性
function Product(){
this.name='iphone'
}
Product.prototype={
age:100
}
var iphone = new Product()
console.log(iphone.hasOwnProperty('name')) //true
console.log(iphone.hasOwnProperty('age')) //false,原型下面的属性

constructor 

        //constructor : 查看对象的构造函数
function Product(){
}
var iphone = new Product();
alert( iphone.constructor ); //Product
var arr = [];
alert( arr.constructor == Array ); //true

面相对象术语

原型构造函数

原型对象
1.原型对象里面的属性 -- 简称原型属性

Product.prototype.age = 12;

2.原型方法
Product.prototype.add=function(){}

//实例化 抽象 具体 实例 --- new Product ---类名
//使用的使用 需要先实例化:
var product = new Product(); //实例对象 实例
//如何访问对象里面的方法属性 -- 点语法
console.log(product.name)
product.add();

构造函数对象的属性和原型对象的属性区别
原型对象属性 原型对象方法 语法规范

    //构造函数对象的属性和原型对象的属性
//构造函数对象属性不共享 原型对象属性共享
var iphone =new Product('iphone')
var android =new Product('android') //构造函数对象属性不共享
console.log(iphone.name) //iphone
console.log(android.name) //android //原型对象属性被所有实例共享
console.log(iphone.date) //2015/10/0
console.log(android.date) //2015/10/0 

字面量

    //简单字面量 - 描述现实世界
var book ={name:'盗墓笔记',price:100}
var product={name:'iphone4s',price:6000}
console.log(product.name)
  //复杂字面量
var book = {
name : "盗墓笔记",
"main title" : "悬疑类小说",
//当属性名中间有空格,或者“-”时,要用引号 把 属性名括起来
author : {
//对象的属性也可以是对象
name : "徐磊",
nickname : "南派三叔",
works:[{name:'盗墓笔记',data:'2010'},{name:'大漠苍狼',data:'2011'},{name:'怒江之战',data:'2012'}]
}
};
console.log(book.name)
console.log(book['main title'])
console.log(book.author.name)

继承

前面讲过js中的面向对象其实是两个对象,一般构造函数对象中放置属性,原型对象中放置所有实例共享的方法
构造函数创建的实例为什么能访问原型对象的方法属性 -- 继承
构造函数对象

function Person(name, sex) {
this.name = name;
this.sex = sex;
} 

// 定义Person的原型,原型中的属性可以被自定义对象引用
// 两个对象的本质关系:原型对象继承了构造函数对象,因而可以访问构造函数对象的一切方法,属性

Person.prototype = {
getName: function() {
return this.name;
},
getSex: function() {
return this.sex;
}
}