当前位置: 代码迷 >> 综合 >> JavaScript day03
  详细解决方案

JavaScript day03

热度:40   发布时间:2023-12-02 19:09:50.0

基本类型:String、Number、Boolean、
引用类型:对象、函数、数组
特殊:null、undefined
弱数据类型
对象:保存复杂的数据,多个属性、方法的集合
ECMA-262对象的定义:无序属性的集合,其属性可以包含基本值,对象,或者函数。可以将对象想象成散列表:键值对,其中值可以是数据或者函数。ECMAScript中的对象其实就是一组数据(属性)和功能(方法)的集合。
对象是一个包含相关数据和方法的集合(通常由一些变量和函数组成,我们称之为对象里面的属性和方法)

var obj = {
    name:"terry",age:12,sayName:function(){
    console.log(this.name);},sayAge:function(){
    console.log(this.age);}
}

1.对象的创建
创建Object实例
使用构造函数创建,new Object()
var person = new Object();
person.name = “briup”;
person.age = 22;
使用对象字面量表示法
不同的属性之间用’,‘分割,属性名和属性值之间用’:'分割

var person = {
    name : "briup",age : 22	
};

对象的初始化有两种方式,构造函数模式和字面量模式
?字面量模式
对象使用"{}“作为对象的边界,对象是由多个属性组成,属性与属性之间通过”,“隔开,属性名与属性值通过”:"隔开;属性名一般不添加引号(当属性名中出现特殊字符的时候需要添加引号),属性值如果是字符串的一定添加引号。

var obj = {
    name:"terry",age:12,sayName:function(){
    console.log("my name is ",this.name);}
}

?构造函数模式
使用Object或者使用自定义构造函数来初始化对象(例如Student)

var obj = new Object();
obj.name = "terry";
obj.age = 12;
obj.sayName = function(){
    console.log("my name is",this.name);
}

//等价于 <==>

var obj={
    };
obj.name="terry";
obj.age=12;

2.对象的访问
访问对象属性
点表示法,右侧必须是以属性名称命名的简单标识符
person.name
中括号表示法
中括号中必须是一个计算结果为字符串的表达式,可以通过变量访问属性,如果属性名中含语法错误的字符,或者属性名使用的是关键字或保留字,可以使用中括号
person[“first name”]
?属性访问
属性访问方式也有两种,点访问、中括号访问
点后面直接跟的是对象的属性,如果属性存在可以访问到,如果属性不存在,得到undefined。 中括号中放的是变量,中括号可以将该变量进行解析。
obj.name //‘terry’
var name = “name”
obj[name] //‘terry’
name = “age”
obj[name] //12
?方法的访问
方法的访问主要是为了执行该对象中的方法,需要按照函数调用的方式去使用
//以下执行结果不一样
obj.sayName;
obj.sayName();//方法的使用
?遍历对象中的属性
普通版的for循环可以遍历数组,但无法遍历对象
增强版的for循环:
for…in用于遍历数组或者对象的属性
for(自定义变量名 in 数组/对象){
执行代码
}
for(var key in obj){
var value=obj[key];
}
obj对象:依次从obj中获取到属性名
“自定义变量名key”用来指定是数组的元素索引,也可以是对象的属性

vi  for-in.js
//循环对象属性:
var obj = {
    name:"briup",age:12,salary:10000
};
/* 两种方式访问属性: objectName.propertyName 或者 objectName["propertyName"] */
console.log(obj.name);
console.log(obj["age"]);
console.log(obj.salary);
for(var key in obj){
    console.log(key+"--"+obj[key]);
}

3.删除对象中的属性
delete只是断开了属性和宿主对象的联系,而不会操作属性中的属性,并且delete只会删除自有属性,不能删除继承属性。在销毁对象时,为了防止内存泄露,遍历对象中的属性,依次删除所有属性。
语法:delete 属性访问表达式
例如:
delete stu.name //删除学生对象中的name属性
只能删除对象的自有属性
delete obj.pro
delete obj[“proname”]
delete obj.sayName //从obj对象中删除sayName属性

4.新增属性并赋值
Obj.newproname=”value”
5.数据类型转换
Vi object-cast.js

// Object类型到Boolean类型
// 除了空引用(null)会转换为false,其他都被转换为true
var obj = {
    name:"briup",age:12
};
console.log(Boolean(obj));
// Object类型转换为String类型
var obj = {
    name:"briup",age:12,toString:function(){
    return this.name+"--"+this.age;}
};
console.log(obj.toString());
console.log(String(obj));
// Object类型转换为Number类型
// valueOf() toString()
/*1.如果只重写了valueOf()或者toString()方法,则调用该方法,并将返回值用Number()转换。2.如果两个方法都重写了,则调用valueOf(),并将返回值用Number()转换。3.如果两个方法都没有重写,则返回NaN */ 
var obj = {
    name:"briup",age:12,toString:function(){
    return "100";},valueOf:function(){
    return 10;}
};
console.log(Number(obj));

6.检测属性
in 检测某属性是否是某对象的自有属性或者是继承属性
Object.prototype.hasOwnProperty()检测给定的属性是否是对象的自有属性,对于继承属性将返回false
Object.prototype.propertyIsEnumerable() 检测给定的属性是否是该对象的自有属性,并且该属性是可枚举的。通常由JS代码创建的属性都是可枚举的,但是可以使用特殊的方法改变可枚举性。
例如:
var o = {
x:1
}
o.hasOwnProperty(“x”); //true,x 为o的自有属性
o.hasOwnProperty(“y”); //false,o 中不存在属性y
o.hasOwnProperty(“toString”); //false,toString为继承属性
o.propertyIsEnumerable(“toString”); //false,不可枚举
var obj= {
name: ‘zs’,
age: 18,
school: ‘大学’
};
‘name’ in obj; // true
‘grade’ in obj; // false
“name” in p1
var b=“first” in p1
//如果用in判断一个属性存在,这个属性不一定是obj的,它可能是obj继承得到的,如:
‘toString’ in obj; // true
//因为toString定义在object对象中,而所有对象最终都会在原型链上指向object,所以obj也拥有toString属性。
//要判断一个属性是否是obj自身拥有的,而不是继承得到的,可以用hasOwnProperty()方法:
obj.hasOwnProperty(‘name’); // true
obj.hasOwnProperty(‘toString’); // false
7.Object根构造函数的原型
Object构造函数原型对象中的部分属性及方法
Object原型中的所具有的任何属性和方法也同样存在于其他对象中,任何对象继承自Object。Object原型中常用的方法:
constructor 保存用户创建当前对象的函数,与原型对象对应的构造函数
hasOwnProperty(propertyName) 检查给定的属性名是否是对象的自有属性
propertyIsEnumerable(propertyName) 检查给定的属性在当前对象实例中是否存在
valueOf() 返回对象的字符串,数值,布尔值的表示
toLocaleString() 返回对象的字符串表示,该字符串与执行环境的地区对应
toString() 返回对象的字符串表示
isPrototypeOf(object) 检查传入的对象的原型
Object.prototype.isPrototypeOf(obj) true
a.isPrototypeOf(b) 如果a是b的原型,则返回true。如果b不是对象,或者a不是b的原型,则返回false。

静态方法即构造函数里方法,实例方法即构造函数原型里方法

封装特性:将创建对象的过程封装起来
所有的构造函数都直接或间接继承Object,实例可以访问其构造函数及其父构造函数原型中的方法。Object.prototype中定义了很多公共的属性和方法,可以让所有的实例对象调用。
?toSource()
返回字符串表示此对象的源代码形式,可以使用此字符串生成一个新的相同的对象。
? propertyIsEnumerable(prop)
判断某个属性是否是该对象的自有属性,并且该属性是可枚举的。通常由JS代码创建的属性都是可枚举的,但是可以使用特殊的方法改变可枚举性。
vi object.js
var now = new Date();
console.log(now);
console.log(now.toString());//Thu Oct 15 2020 21:40:38 GMT+0800 (中国标准时间)
console.log(now.toLocaleString());//2020/10/15 下午9:40:38

var obj = new Object();
obj.name = "terry";
obj.age = 12;
obj.gender="male"
//Object根构造函数
//Object.prototype根父类
console.log(obj.toString());
console.log(obj.valueOf());
console.log(obj.hasOwnProperty("name"));
console.log("name" in obj);
console.log(obj.propertyIsEnumerable("name"));
console.log(Object.getOwnPropertyDescriptor(obj,"name"));console.log(Object,typeof Object);//构造函数
console.log(Object.prototype,typeof Object.prototype);//原型
console.log(Object.prototype.constructor === Object);//构造函数
console.log(obj,typeof obj);//孩子
console.log(obj.__proto__);//父亲-原型,内部属性,不可迭代的属性
console.log(obj.__proto__ === Object.prototype);//true
//constructor是父亲的属性   父亲-孩子:继承
console.log(obj.constructor);//母亲-构造函数
console.log(obj.constructor === Object);//true
Vi useproperty.js
var obj={name:"zs",age:12};
obj.hasOwnProperty("age");//true
obj.hasOwnProperty("gender");//false
obj.hasOwnProperty("constructor");//false
"age" in obj; //true
"gender" in obj;//false
"constructor" in obj;//true
Object.prototype.test=”ttttt”;
obj.hasOwnProperty("test");//false
console.log(obj.test);//爷爷:Object.prototype  父亲:String.prototype 儿子:str
var str=new String("hello");
console.log(str.test);//ttttt
str.hasOwnProperty("length");//true
str.hasOwnProperty("test");//false
//是否是同一家族的
String.prototype.isPrototypeOf(str);
Object.prototype.isPrototypeOf(str);
String.prototype.isPrototypeOf(obj);
obj instanceof String
str instanceof String//enumerable:true
for(var i in obj){console.log(i+"--"+obj[i]);
}

8.深入理解对象-定义属性
ECMAScript中有两种属性:数据属性、访问器属性。这两种属性用于设置属性的高级属性,例如该属性是否可以配置,是否可以读写,是否可以遍历,并且可以通过setter,getter来监听数据的改变。
?数据属性特性
数据属性 例如name属性
包含一个属性值的位置,这个位置可以读取和写入值。数据属性特性如下
[[Configurable]]
表示是否通过delete删除属性从而重新定义属性,能否修改属性的特性,或者能否把属性修改为访问器属性(属性直接定义在对象中,默认为true)。 当为false时,不能重新定义不能使用delete删除。
[[Enumerable]]
表示能否通过for-in循环返回属性。(属性直接定义在对象中,默认为true)
[[Writable]] 表示能否修改属性的值。(属性直接定义在对象中,默认为true)
[[Value]] 包含这个属性的数据值 name:jacky
要修改属性默认的特性,必须使用ECMAScript5的Object.defineProperty(属性所在的对象,属性的名字,一个描述符对象)方法
修改属性的默认特性可以使用
Object.defineProperty(obj,property,options) 或者
Object.defineProperties(obj,{
property:options,
property:options,

})
Object.defineProperty(obj,‘name’,{
configurable:true,
enumerable:true,
writable:true,
value:‘terry’
})
console.log(obj.name);
Object.defineProperty(obj,“name”,{enumerable:false})
obj.propertyIsEnumerable(“name”);//false
注意:当我们创建一个对象并且为对象设置一个属性的时候,该属性默认特性Configurable、Enumerable、Writable默认都为true,value为该属性的值。
?访问器属性特性
访问器属性 例如:_year–> year(访问器属性)
访问器属性不包含数据值,包含的是一对get和set方法,在读写访问器属性时,就是通过这两个方法来进行操作处理的。访问器属性不能直接定义,要通过Object.defineProperty()这个Object的静态方法来定义。
访问器属性有如下特性:
[[Configurable]]
表示是否通过delete删除属性从而重新定义属性,能否修改属性的特性,或者能否把属性修改为访问器属性(默认为false)。
[[Enumerable]]
表示能否通过for-in循环返回属性(默认为false)。
[[Get]] 在获取属性时调用的函数,默认为undefined
[[Set]] 在写入属性时调用的函数,默认为undefined

使用Object的defineProperty静态方法可以定义对象中的单个数据属性或者访问器属性
var book = { _year :2004,edition:1}
Object.defineProperty(book,“year”,{
get:function(){return this._year;},
set:function(year){this._year =year;}
});
Object.defineProperty(book,"_year",{
enumerable:false
});
_year前面的下划线是一种常用的记号,用来表示只能通过对象方法访问的属性。而访问器属性year则包含一个get函数和一个set函数。

访问器属性包含一对setter和getter函数(这两个函数可以缺省),在读取访问其属性时,会调用getter函数,这个函数负责返回有效的值;在写入访问器属性时,会调用setter函数并传入新值,这个函数负责决定如何处理数据。定义setter、getter必须通过Object.defineProperty(obj,property,options), 访问器属性可以通过Object.getOwnPropertyDescriptor()查询。

var book = {
    _name:'',   // 内置属性age:12
}Object.defineProperty(book,'name',{
    configurable:true,enumerable:true,get:function(){
    return this._name;},set:function(v){
    this._name = "charles "+v}
})console.log(book);
book.name = 'terry';
console.log(book.name)Vi getset.jsvar obj={
    name:"zs",_age:12}//_age前面的下划线是一种约定,代表属性私有console.log(obj.name,obj._age,obj.age);//'zs' 12 undefined//定义的访问器属性Object.defineProperty,在对象是是不存在的属性Object.defineProperty(obj,"age",{
    get:function(){
    return this._age;},set:function(newage){
    console.log("生日到了,准备礼物...");this._age=newage;if(newage>18) this.name="ww";//想要的一些操作行为//Object.defineProperty()定义了访问器属性(age),当age属性修改时,name属性和_age属性会相应修改。}});console.log(obj.name,obj._age,obj.age);//'zs' 12 12obj.age=30;console.log(obj.name,obj._age,obj.age);//ww 30 30Object.getOwnPropertyDescriptor(obj,"name");Object.getOwnPropertyDescriptor(obj,"_age");Object.getOwnPropertyDescriptor(obj,"age");//enumerable:true//name--ww//_age--30for(var i in obj){
    console.log(i+"--"+obj[i]);}//enumerableObject.defineProperty(obj,"age2",{
    get:function(){
    return this._age;},set:function(age){
    this._age=age;},enumerable: true});for(var i in obj){
    console.log(i+"--"+obj[i]);}//数据的影响:obj.age=100;console.log(obj.age,obj._age);obj._age=200;console.log(obj.age,obj._age);由此可以想到数据的双向绑定:在一个对象(person)中设置一个私有属性(_age:开头下划线代表私有属性),再为这个对象设置访问器属性age(本身还未在对象中定义),当person.age进行修改时触发set函数,通过这个函数可以进行数据的操作,比如数据的判断赋值等一系列操作,从而实现数据的双向绑定。这个原理是vue的本质原理。vue是数据驱动框架,当数据发生改变的时候,视图自动更新。

?定义多个属性
Object.defineProperties() Object的静态方法
该方法接受两个对象参数,第一个参数是要添加或者要修改属性的对象,第二个参数是对象的属性和属性的描述

  var book = {
    };Object.defineProperties(book,{
    _year :{
    //数据属性value:1001},edition :{
    //数据属性value:1},year :{
    //访问器属性get:function(){
    return this._year+1},set:function(year){
    this._year = year}}});console.log(book.year);    

?读取属性的特性
Object.getOwnPropertyDescriptor()
获取指定属性的描述符该方法接受两个参数,第一个为属性所在的对象,第二个为要读取其描述符的属性名称
var descriptor = Object.getOwnPropertyDescriptor(book,"_year");
console.log(descriptor.value); //1001
console.log(descriptor.configurable) //false
通过Object.getOwnPropertyDescriptor()可以查询特性
通过Object.defineProperty()可以修改其特性

Object.getOwnPropertyDescriptor(obj,propname)
Object.defineProperty(obj,propname,{});
Object.defineProperties(obj,{pn1:{},pn2:{},pn3:{}});
{configurable:true,enumerable:true,writable:true,value:xxx}Vi property.js
var obj={name:"zs",age:12};
Object.defineProperty(obj,"name",{configurable:false,enumerable:false,writable:false,value:"lisi"});Object.getOwnPropertyDescriptor(obj,"name");
Object.getOwnPropertyDescriptor(obj,"age");
//enumerable:true
console.log(obj);
console.log(obj.valueOf());
for(var i in obj){console.log(i+"--"+obj[i]);
}
//value值已经发生了变化
console.log(obj.name);
obj.age=13;
Object.getOwnPropertyDescriptor(obj,"age");
//writable:true
obj.name="ww";
obj.age=22;
console.log(obj.name,obj.age);//lisi 22
//configurable:true
delete obj.name;//false
delete obj.age;//true
console.log(obj.name,obj.age);//lisi undefined
//多个属性特征一起设置
obj.gender="male";
Object.defineProperty(obj,"gender",{value:"winnie",configurable:true});
Object.getOwnPropertyDescriptor(obj,"gender");
obj.sno=101;
Object.defineProperties(obj,
{"gender":{value:"female",writable:false},"sno":{enumerable:false}}
);
console.log(obj);
Object.getOwnPropertyDescriptor(obj,"gender");
Object.getOwnPropertyDescriptor(obj,"sno");

9.值传递与引用传递(址传递)
基本数据类型的变量:
可以直接操作保存在变量中的实际的值
参数传递的时候传递的是实际值
引用数据类型的变量:
不能直接操作对象的内存空间,实际上是在操作对象的引用。可以为引用类型变量添加属性和方法,也可以改变和删除其属性和方法。
参数传递的时候传递的是引用地址。

var a=10;
var obj1={
    name:'zs'};
//复制
var b=a;
var obj2=obj1;
console.log(a,b);
b=20;
console.log(a,b);//值传递
console.log(obj1,obj2);
obj2.name='ls';
console.log(obj1,obj2);//引用传递
var obj3={
    };
for(var k in obj1){
    
obj3[k] = obj1[k];
}
obj3.name='ww';
console.log(obj1,obj2,obj3);
//值传递:不受影响
//引用传递:受影响, 内存堆中的地址的值
function add(a,b){
     
a++;
b.age++;
console.log(a,b);
}
var v1=10;
var v2={
    age:20};
add(v1,v2);
console.log(v1,v2);

10.对象序列化
对象序列化是指将对象的状态转换为字符串,也可以反序列化,将字符串还原为对象函数,RegExp,Error对象,undefined值不能序列化和反序列化。
JSON.stringify(obj) 将对象序列化为Json字符串,只能序列化对象可枚举的自有属性
JSON.parse(jsonStr) 反序列化
将对象转换为字符串的描述,解决对象在io中传递的问题

  1. 常规转换
    obj.toString()
  2. 转换为json字符串
    JSON.stringify(obj)
  3. 转换为查询字符串
    var qs = require(‘querystring’)
    qs.stringify(obj)

vi object-json.js

// 将对象转换为JSON字符串
// {"name":"briup","age":12}
var obj = {
    name:"briup",age:12
};
console.log(obj);  //object类型打印的结果 {name:'briup',age:12}
// 将对象转换为JSON字符串
var json = JSON.stringify(obj);
console.log(json);//string类型的字符串
// 将JSON字符串转换为对象
var json = '{"name":"briup","age":12}';
var obj = JSON.parse(json);
console.log(obj);
  相关解决方案