知识梳理之对象,数据类型

对象属性

两种数据类型

六种基础数据类型

六种基础数据类型(null,undefined,boolean,string,number,symbol)
以key,value 存取在栈区

 var str = '123' ;
 var num = 1;
 var bol =true;
 var km = null;
 //es6中定义一种独一无二的值
 var sym=Symbol("name");
三种常用引用类型

3种常用引用类型:object ,array,function 栈区存放的是指针(地址),值是放在堆中的

var arr=[];
var obj={}
var fun=function(){};
const kk={name:"xj"};
kk.color="red";
console.log(kk);//Object {name: "xj", color: "red"}
const kk2="xj";
kk2="kk";
console.log(kk2);//Uncaught TypeError: Assignment to constant variable.

var obj = new Object();
var obj_arr= new Array();
//实例化了一个String对象,不是基本数据类型
var s1 = new String('123');
var s4 = new String('123');
//实例化的s1和s4都是实例化的一个对象,对象都是引用类型,所以s1和s4 是不相等的。
s1==s4 //false  

//函数传参
var s2 = String('123');
//直接字面量
var s3='123';
console.log(s1,s2,s3);//String {0: "1", 1: "2", 2: "3", length: 3, [[PrimitiveValue]]: "123"}0: "1"1: "2"2: "3"length: 3__proto__: String[[PrimitiveValue]]: "123" "123" "123"
s1===s2;//false
s1===s3;//false
s2===s3;//true
s1==s2;//true
s2==s3;//true
s1==s3;//true
//等号运算符,从左往右
s1==s2==s3;//false

预解析

预解析只能发生在通过var 和function定义的关键字身上。
预解析案例:

// 案例1
var a=1;
function f(){
console.log(a); //1 读取外部的变量1
a=2;
console.log(a); //2 全局变量a的值改为2
}
f();
console.log(a); //2 a的值为2
//案例2
var a;
var b;
(function(){
console.log(a); //undefined
console.log(b); //undefined
var a=b=3;  //等价于 var a=3; b=3;
console.log(a); //3  a为局部变量
console.log(b); //3
})();
console.log(a); //undefined  
console.log(b); //3
//案例3
var a = 1;
function f(){
 console.log(a); //undefined
 var a = 3;
 console.log(a); //3
}
f(); 
console.log(a); //1
//案例4
  var a = 1;               
   function f(){
         console.log(a);   //undefined            
         a = 2;              
         console.log(a);   //2        
         var a = 3;                                              
         console.log(a); //3
     }
     f();                
     console.log(a); //1
//案例5
var a=1;
function f(){
   console.log(a); //1
    a=2;
   console.log(a); //2
}
f(); 
console.log(a); //2

两种数据类型的区别

类比面试选人(来自哪里(位置),可靠性(忠诚度),干活情况(复制),选谁(各自擅长领域比较),薪资(内存分配和垃圾回收))

1.值是否可变

基本类型的值是不可变的,除非重新给他赋值,引用类型的值是可变的

2.比较,是否两个数据类型的比较

基本类型的比较是值的比较
引用类型的比较是引用的比较

3.值存放的位置

基本类型的变量是存放在栈区的(栈区指内存里的栈内存),引用类型的值是同时保存在栈内存和堆内 存中的对象

4.复制的情况

复制时,基本类型是直接复制了一个新的变量,新旧两个变量之间没有关系 引用类型复制了新的变量,但这个变量是一个指针,新旧两个指针指向同一个对象

内存分配和垃圾回收

一般来说栈内存线性有序存储,容量小,系统分配效率高。而堆内存首先要在堆内存新分配存储区域, 之后又要把指针存储到栈内存中,效率相对就要低一些了。 垃圾回收方面,栈内存变量基本上用完就回收了,而堆内存中的变量因为存在很多不确定的引用,只有当所有调用的变量全部销毁之后才能回收。

JavaScript 变量均为对象。当您声明一个变量时,就创建了一个新的对象。

//基本数据类型是值传递(函数内部的值发生改变不会传到外部)
var num = 50;
function add(num){
num =100;
}
add(100);
console.log(num);//50
//引用类型是引用传递(函数内部的值发生改变会传到外部)
var arr = [1,2,3];
function add(num){
arr[0]=99;
}
add(arr);
console.log(arr);
//基础数据类型比较
var a=1;
var c==true;
var b=1;
a===b;//true
a==c;//true
a===c;//false

//引用类型
var p1={};
var p2={};
p1===p2; false

//关于值传递 (函数内部的更改不影响外部)
 var num = 50; 
 function add(num){
  num=100; 
  }
  add(num);
  console.log(num);//50
  
 // 引用(指针 | 快捷方式)传递 (函数内部的更改会影响外部) 
 var arr = [10,20,30]; 
 function add2(arr){ 
 arr[0]=99; 
 }
 add2(arr);
 console.log(arr);//[99,20,30]

检测数据类型

基本数据类型检测:
//**typeof 无法区分数组和对象**
    typeof 2;    // number
    typeof '123';    //string
    typeof {};      //object
    typeof [];      //object
    typeof true;    //boolen
    typeof (function(){}); //function
]
      
引用类型(对象类型)检测
用来更精准的控制对象的数据类型检测(包含数组和对象)

Object.prototype.toString.call();

//**对象的原生原型扩展函数**:
 Object.prototype.toString.call('aaaa') // [object String] 
 Object.prototype.toString.call(2222) // [object Number] 
 Object.prototype.toString.call(true) // [object Boolean] 
 Object.prototype.toString.call(undefined) // [object Undefined]
 Object.prototype.toString.call(null) // [object Null] 
 Object.prototype.toString.call({}) // [object Object] 
 Object.prototype.toString.call([]) // [object Array] 
 Object.prototype.toString.call(function(){}) // [object Function]
 var mm =document.querySelector('body');
 Object.prototype.toString.call(mm);//"[object HTMLBodyElement]"
instanceof 运算符用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链
//instanceof 用于判断一个变量是否某个对象的实例
function Car(make, model, year) {
  this.make = make;
  this.model = model;
  this.year = year;
}
var auto = new Car('Honda', 'Accord', 1998);

console.log(auto instanceof Car);
// expected output: true
console.log(auto instanceof Object);
// expected output: true'

constructor 也能判断数据类型
//constructor 也能判断数据类型
var obj = new Object();
obj.constructor===Object;//true
console.log(obj.constructor);
var arr = new Array();
arr.constructor === Array;//true

创建对象的五种方式

1.通过Object 类创建对象

优点:简单容易理解
缺点:不能批量生产

var arr1 = new Array();
var str = new String();
var obj1 = new Object();
obj1.name="xj";
obj1.sayName=function(){
console.log("他说:" + this.name);
};
obj1.sayName();

2.通过字面量创建对象

字面量:一般情况下,除去表达式,等号赋值符右边都可以认为是字面量。
优点:简单容易理解
缺点:不能批量生产

//简单字面量
var obj2 = {};
obj2.name="xj";
obj2.sayName=function(){
console.log(this.name+this.age);
}
obj2["age"]=18;
obj2.sayName();
//嵌套字面量
var obj3 = {
name:"xj",
age:18,
sayName:function(){
console.log(this.name+this.age);
}
}
obj3.sayName();

3.工厂方式定义

定义一个函数声明,将参数传入,里面通过object构造函数,最后将创建的对象进行返回
优点:可以实现批量生产
缺点:不能检测出对象是由谁来产生的

function createObj(name,age){
 var obj = new Object();
 obj.name=name;
 obj.age=age;
 obj.sayName=function(){
 console.log(obj.name+obj.age);
 }
 return obj;
}
var obj1 = createObj("xj",16);
var obj2 = createObj("mjf",18);
obj1.sayName();
obj2.sayName();

4.构造函数方式定义

优点:可以知道对象由谁产生的
缺点:会创造新的独立空间来盛放相同的方法,造成空间浪费。
new的过程中做了四件事
1.创建了一个新的对象
2.this指向了新创建的对象
3.执行构造函数的代码
4.返回新的对象

function createObj(name,age){
this.name = name;
this.age = age;
this.sayName=function(){
console.log(this.name+this.age);
}
}
var obj1 = new createObj("xj",16);
obj1.sayName();
var obj2 = new createObj("mjf",18);
obj2.sayName();

5.通过Object.create 方式定义

优点:将一个对象作为另一个对象的原型实现继承

var obj1 = {
name:"xj",
sayName:function(){
console.log(this.name);
}
}
//obj2对象的原型指向obj1
//可以达到一种继承的目的
var obj2 = Object.create(obj1);
console.log(obj2.sayName());

6.原型方式创建对象

优点:实现继承解决构造函数空间浪费问题
缺点:不能定制

function Animal(){}
Animal.prototype.name="猫";
Animal.prototype.say=function(){
console.log(this.name);
}
var cat = new Animal();
cat.say=function(){
console.log("miaomiao"+this.name);
}
cat.say();

7.混合模式

优点:既实现了定制也实现了继承

function Animal(name,age,sex){
this.name=name;
this.age=age;
this.sex=sex;
}
Animal.prototype.type="动物";
var cat = new Animal('小白',3,'雌');
cat.call=function(){
console.log(this.type+":"+this.name+this.sex)
}
cat.call();


8.class 类定义对象

Javascript中的类是基于原型继承的语法糖

语法:
  class name{
    constructor( ){
      相当于混合模式的构造函数
    }
    放在constructor外面的方法或者是属性(这个位置的代码相当于混合模式中的原型对象上的方法)
  }
如何实现类与类之间的继承?
  可以通过extends关键字来实现:
语法(比如类B需要继承类A):
  class A{ };
  class B extends A{
    constructor( ){
      super( )//调用类A
    }
  };


class Tab{
constructor(){}//没有的话可以省略 ***
    init(){
        var leng = this.btns.length;
        var that = this;
        for(var i=0;i<leng;i++){
            this.btns[i].index = i;
            this.btns[i].addEventListener("click",function(){
                for(var j=0;j<leng;j++){
                    that.content[j].style.display = "none";
                }
                that.content[this.index].style.display = "block";
            })
        }
    }
}
            
class Tabchild extends Tab{
    constructor(el){
        super();//调用
        this.el = document.querySelector(el);//获取到选项卡最大的容器
        this.btns = this.el.querySelector(".btns").children;//获取所有按钮
        this.content = this.el.querySelector(".content").children;//获取内容    
    }
}
             
var tab = new Tabchild(".tab");
tab.init();

过程式开发与面向对象开发

面向过程

站在执行者的角度
洗衣服:
1.找盆,找洗衣液
2.收集要洗的衣服
3.放水,放洗衣液
4.洗一洗
5.晒一晒

面向对象

站在指挥者的角度
1.找个对象
2.让他去洗
3.检查是否洗好晒干

面相对象的三大特点

封装

封装是隐藏对象的属性和实现细节,仅对外提供公共访问的接口,(方式),将变化隔离,便于使用,可以提高复用性和安全性。

继承

继承是提高代码的复用性,是多态的前提。

多态

多态是指相同的操作或函数,过程可作用于多种类型的对象上并获得不同的结果,收到同一消息产生不同的结果,这种现象称为多态。

面向对象的五大基本原则

单一职责原则:

类的功能要单一,不能包罗万象,跟杂货铺似的。

开放封闭原则

一个模块对于拓展是开放的,对于修改是封闭的,想要增加功能热烈欢迎,想要修改,万万不能

接口分离原则

设计时采用多个特定客户类有关的接口采用一个通用接口

1.抽象可以将复杂的问题更加简单化
2.从以前面向过程的 执行者,变成了张张嘴的指挥者
3.面向对象更符合人类的思维,面向过程是机器的思想。

内部对象

Array,Object,Data,Math,RegExp,String ,Error,EvalError,TypeError
Math使用时不需要实例化

浏览器对象(宿主对象)

window ,document,screen history,locaton
不同浏览器提供的宿主对象可能不同,即使提供的对象相同,其实现的方式也可能不一样,这样就会存在兼容性问题。

    //FormData 对象用以将数据编译成键值对,以便用 XMLHttpRequest 来发送数据。其主要用于发送表单数据
    var formData = new FormData();
    formData.append('username':'xj');
    formData.append('age':16);
 //判断图片是否加载完成
   var img = new Image();
    img.src='...';
    img.onload = function(){
        //图片加载完成
    }
    

自定义对象

对象(object)是数据的无序集合,其中数据包括基本类型、函数其他对象。对象的功能是它们将特定任务所需要的所有数据和行为收集到一个地方。

函数对象和普通对象的区别:

函数对象都有prototype属性,普通对象没有
任何一个对象都有__proto__

对象属性的读取

属性读取可以使用.和[]
[]里面可以盛放变量和数字。

var obj={
name:'xj',
1:'hello',
sleep:function(){
console.log(this.name);
}
}
obj.name //xj
obj['name'] //xj
var test='name'; 
obj[test]//xj
obj[1] //hello
obj.sleep();//hello

设置对象属性

通过. [] object.defineProperty

var obj={}
obj.name="xj";
obj['age']=16;
Object.defineProperty(obj,'weight',{
value:"100",
//默认为false 
writable:true,//是否可改
enumerable:true,//是否可枚举
cofigurable:true,//是否可删除
})

删除对象属性

delete()方法只能够删除自有属性,不能够删除继承属性。delete()只是断开属性和宿主对象的联系,而 不会去操作属性中的属性。

var obj = Object.create({"name":"xjj"},{
hobby:{
value:"singsong",
writable:true,
enumerable:true,
configurable:true,
},
fool:{
value:"is not true"
}
})
//执行成功,但是无法删除继承来的属性
delete obj.name 
//删除成功
delete obj.hobby 
//因为configurable为false无法删除
delete obj.fool

对象属性查找

属性的查找路径: 假设读取某个对象的属性 x,首先会在此对象的实例属性中查找。若没有找到,将会 在此对象的原型对象中查找属性 x。若原型对象也没有属性 x,将继续查找这个原型对象的原型(假设原 型对象含有原型),一直到找到属性 x 或者无原型为止。

属性检测

for in用来检测某个对象上是否含有某属性(包含实例属性和继承来的属性)
hasOwnProperty 判断该属性是不是自身对象上的,而不是继承得来的
propertyIsEnumerable: //判断属性是否为可枚举性的,true 时可以被 for in 循环到,false 就不能被循环到

var obj = Object.create({"name":"xjj"},{
hobby:{
value:"singsong",
writable:true,
enumerable:true,
configurable:true,
},
fool:{
value:"is not true"
}
})
'hobby' in obj //true
for(item in obj){
//只遍历自有的实例属性
if(obj.hasOwnProperty(item)){
 console.log(item);//hobby 实例属性
 console.log(obj[item]);//singsong
}

console.log(item);//hobby,name obj上面所有能够遍历出来的属性(包含继承的属性)
}
obj.propertyisEnumerable('fool');//false 不可枚举的

对象属性遍历

for in 语句块 object.keys,Objec.getOwnPopertyNames(obj)
1.使用 for…in…遍历 遍历对象可枚举的实例属性和继承属性
2.使用 Object.keys()遍历 ,Object.values() 返回一个数组,包含对象可枚举的实例属性名称
3.使用 Object.getOwnPropertyNames(obj)遍历 返回一个数组,包含对象的所有实例属性名称。包括可枚举和不可枚举的

//默认都为true
var test={
name:"xjj"
}
//默认都为false
var obj = Object.create(test,{
hobby:{
value:"singsong",
writable:true,
enumerable:true,
configurable:true,
},
fool:{
value:"is not true"
}
})
obj.name="xj";
obj['age']=16;
Object.defineProperty(obj,'weight',{
value : 100,
//默认为false 
writable:true,//是否可改
enumerable:true,//是否可枚举
cofigurable:true,//是否可删除
})

//可枚举的实例属性
for(item in obj){
console.log(item);//hobby name age weight
console.log(obj[item]);
}
var keysObj=Object.keys(obj);
console.log(keysObj)//["hobby", "name", "age", "weight"]
keysObj.forEach(function(key,index){
console.log(key,index,obj[key]);
//hobby 0 singsong
// name 1 xj
//age 2 16
// weight 3 100
})
//当前对象可枚举的自身属性
delete obj.name
var values=Object.values(obj);
console.log(values);//["singsong", 16, 100]
//当前对象可枚举的所有属性(包含继承)
for(item2 in obj){
console.log(item2);//hobby name age weight
console.log(obj[item2]);//singsong xjj 16 100
}
//包括可枚举和不可枚举的自身属性
Object.getOwnpropertyNames(obj);//["hobby", "fool","age", "weight"]
Object.getOwnpropertyNames(obj).forEach(function(key){
console.log(obj[key]);//singsong
//is not true
// 16
//100
})

序列化对象

JSON.stringify()和 JSON.parse()用来序列化和还原 JavaScript 对象。 JSON.stringify(value [, replacer] [, space]) 的原始方法中含有三个参数,
第一个参数是必选的,其中第二个参数和第 三个参数是可选的 第一个参数:必选参数,就是输入的对象
第二个参数:为过滤参数,数组或者方法
第三个参数:可以控制字符串之间的间距,如果是一个数字,则在字符串化时每一个级别会比上一个级别多缩进 c 个字 符

var obj={name:"xj",age:16,sex:"女"}
var obj1 =JSON.stringify(obj);
console.log(obj1);//{"name":"xj","age":16,"sex":"女"}
var obj2 = JSON.parse(obj1);
console.log(obj2);//Object {name: "xj", age: 16, sex: "女"}
var obj3=JSON.stringify(obj,["name","age"]);
console.log(obj3)  //"{"name":"xj","age":16}"
var obj4 =JSON.stringify(obj,['name','age'],8)
obj4
//"{
     //   "name": "xj",
      //  "age": 16
//}"
var obj5 =JSON.stringify(obj,['name','age'],'ok');
obj5
//"{
//ok"name": "xj",
//ok"age": 16
//}"
var obj6 =JSON.stringify(obj,['name','age'],'\t');
obj6
//"{
//	"name": "xj",
//	"age": 16
//}"

属性的特性,属性描述符

属性分为数据属性和访问器属性;

数据属性

数据属性value、writable、enumerable、configurable。
value:设置属性的值
writeable:是否可修改属性的值。
enumerable: 是否可枚举属性;true:可枚举,可通过 for/in 语句枚举属性;false:不可枚举。
configurable: 是否可配置。 是否可以通过 delete 删除属性,能否修改属性的特性,能否把属性修改为访问器属性,默认 false; true:可修改属性的特性false:不可修改属性的特性 属性描述符用来描述属性特性的(只有在内部才能用的特性),配置属性是否可写,是否可枚举,值是多少 ,是否可修改.
注意
(1) 在使用 Object.defineProperty、Object.defineProperties 或 Object.create 函数的情况下添加 数据属性,writable、enumerable 和 configurable 默认值为 false。 (2) 使用对象直接量创建的属性,writable、enumerable 和 configurable 特性默认为 true。

访问器属性:

访问器属性不能直接定义,必须使用 Object.defineProperty()来定义 访问器属性 : set、get、enumerable、configurable。 configurable:true/false,同上;enumerable:true/false,同上;
set:function,修改属性值时调用的函数;
get:function,读取属性值时调用的函数。
**备注:**访问器属性可以起到很好的保护作用,当只有 get 方法时,就实现只读不能写;反之,只有 set 时,便是只能写入而不能读取

JavaScript 中的可枚举属性与不可枚举属性

所有可枚举与否都是开发者自己定义的,可以通过 Object.defineProperty()方法 设置可枚举属性 可枚举的属性就是可以列举出来的属性, 换句话说就是可以用 for in 循环的出来的 其实在上面的例子中已经使用到了设置 enumerable 的方法:Object.defineProperty()

var obj={
name:"xj",
age:15,
sex:"女"
}
Object.defineProperty(obj,{
age:{
writable:false,
configurable:false
},age:{
enumerable:false;
}
})


总结:可枚举属性能够通过 for-in 循环或 Object.keys()返回属性

对象属性:

属性就是 类中包含的变量;每一个对象实例有若干个属性. 为了正确的继承,属性应该被定义在类的原型 属性 (函数)中。

对象方法

调用方法很像存取一个属性, 不同的是在方法名后面很可能带着参数. 为定义一个方法, 需要将一个函数 赋值给类的 prototype 属性; 这个赋值给函数的名称就是用来给对象在外部调用它使用的。

Array 扩展

1 Array.prototype.indexOf(value) : 得到值在数组中的第一个下标
2 Array.prototype.lastIndexOf(value) : 得到值在数组中的最后一个下标
3 Array.prototype.forEach(function(item, index){}) : 遍历数组
4 Array.prototype.map(function(item, index){}) : 遍历数组返回一个新的数组,返回加 工之后的值
5 Array.prototype.filter(function(item, index){}) : 遍历过滤出一个新的子数组, 返回 条件为 true

组件、插件、模块、框架、架构

组件是近代工业化发展的产物,组件的出现时为了实现功能模块化,前提是接口标准化。

组件

组件是封装了一个或多个模块的程序实体,组件也可以说是具有一个完整功能的模块。
特点:
1.组件是递归的,它可以和其他程序代码段连接起来组成一个段更大的程序代码,形成一个更大的组件
2.组件是面向对象里面一个重用的概念,也称为构件,通过不同构件组成一个软件成品。
3.组件之间通过接口进行交互,将有特点的组件称为插件,这些特点是易于系统分离,接口明晰,可以替换的程序模块。
4.组件强调的是封装,在谈论时需要分辨谈论的层次和范围。
使用方法:
组件就是描述一个系统中的实体单元的概念,简而言之,是用来构建你的业务模块的。

插件

插件是一个组件,是一个程序模块也是一个功能模块。
使用方法:
插件是需要满足一定接口规范的功能模块,简而言之,就是用来增强你技术栈的功能模块。

模块

组件和模块是粗细粒度不同的复用块;
定义模块的原则:高内聚,低耦合。

框架

框架是一个可供二次开发的程序实体,框架更看重技术的实现。

架构

架构不仅涉及到结构与行为,而且还涉及到系统的使用,功能,性能,适应性,重用性,可理解性,经济性和技术约束的权衡和美学考虑,更偏向于设计。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值