【JSON.stringify()的运用】【类数组对象转数组】【判断数组是数组】【原型原型链】【闭包】

目录

JSON.stringify()的运用

1.判断数组是否包含某对象,或者判断对象是否相等。

 2.让localStorage/sessionStorage可以存储对象。

3. 深拷贝

类数组对象。。

判断值类型(判断数组是否为数组)

typeof

instanceof

constructor

Object.prototype.toString.call() 或 Object.prototype.toString.apply()

Array.isArray(最靠谱)

原型和原型链

对原型链进行操作的示例

 hasOwnProperty

对象的创建及访问


 

JSON.stringify()的运用

  • JSON.stringify():把任何JavaScript对象变成JSON,就是把这个对象序列化成一个JSON格式的字符串,这样才能够通过网络传递给其他计算机。
  • JSON.parse():如果我们收到一个JSON格式的字符串,只需要把它反序列化成一个JavaScript对象,就可以在JavaScript中直接使用这个对象了。

1.判断数组是否包含某对象,或者判断对象是否相等。

const z = [1,2,3];
const s = [1,2,3]
console.log(JSON.stringify(z) === JSON.stringify(s)) // true
   const data = [{ name: "l" }, { name: "a" }, { name: "k" }];
    const val = { name: "l" };
    console.log(
      typeof JSON.stringify(data),
      JSON.stringify(data).indexOf(JSON.stringify(val)) !== -1
    );
// string true

 2.让localStorage/sessionStorage可以存储对象。

 localStorage/sessionStorage默认只能存储字符串,而实际开发中,我们往往需要存储的数据多为对象类型,那么这里我们就可以在存储时利用json.stringify()将对象转为字符串,而在取缓存时,只需配合json.parse()转回对象即可。

3. 深拷贝

实际开发中,如果怕影响原数据,我们常深拷贝出一份数据做任意操作,其实使用JSON.stringify()与JSON.parse()来实现深拷贝是很不错的选择。(深拷贝的更多内容请见我的另一篇博客)


类数组对象。。

为什么要将类数组对象转化为数组

数组对象Array有很多方法:shift、unshift、splice、slice、concat、reverse、sort,ES6又新增了一些方法:forEach、isArray、indexOf、lastIndexOf、every、some、map、filter、reduce等。由于类数组不具有数组所具有的操作数组的方法,将类数组转换为数组之后就能调用这些强大的方法。

类数组转数组的方法:

判断值类型(判断数组是否为数组)

参考:https://segmentfault.com/a/1190000006150186#item-4

JavaScript有五种方法可以确定一个值到底是什么类型,分别是typeof运算符,constructor法,instanceof运算符,Object.prototype.toString方法以及Array.isArray法。

typeof

const s = 'hello';
console.log(typeof(s))//String

在参数为数组,对象或者null时,typeof返回的结果都是object,使用这种方法并不能识别出数组。

instanceof

instanceof运算符可以用来判断某个构造函数的prototype属性所指向的對象是否存在于另外一个要检测对象的原型链上。

const a = [];
const b = {};
console.log(a instanceof Array);//true
console.log(a instanceof Object);//true,在数组的原型链上也能找到Object构造函数
console.log(b instanceof Array);//false

使用instanceof运算符可以分辨数组和对象,可以判断数组是数组。 

constructor

实例化的数组拥有一个constructor属性,这个属性指向生成这个数组的方法。

//定义一个数组
const a = [];
console.log(a.constructor == Array);//true
//作死将constructor属性改成了别的
a.contrtuctor = Object;
console.log(a.constructor == Array);//false (哭脸)
console.log(a.constructor == Object);//true (哭脸)
console.log(a instanceof Array);//true (instanceof火眼金睛)

Object.prototype.toString.call() 或 Object.prototype.toString.apply()

const isArray = (something)=>{
    return Object.prototype.toString.call(something) === '[object Array]';
}

cosnt a = [];
const b = {};
isArray(a);//true
isArray(b);//false

toString方法返回的是反应这个对象的字符串,那为什么还要调用call()方法: 

toString为Object的原型方法,而Array,function等类型作为Object的实例,都重写了toString方法。不同的对象类型调用toString方法时,根据原型链的知识,调用的是对应的重写之后的toString方法(function类型返回内容为函数体的字符串,Array类型返回元素组成的字符串......),而不会去调用Object上原型toString方法(返回对象的具体类型),所以采用obj.toString()不能得到其对象类型,只能将obj转化为字符串类型;因此,在想要得到对象的具体类型时,应该调用Object上原型toString方法。

var a = [1,2,3];
var b ={v:1};
var c = () => {}
console.log(a.toString())   // ‘1,2,3’
console.log(b.toString)      // "[object Object]"
console.log(c.toString)        //  "()=>{}"

Array.isArray(最靠谱)

const ooo = ["zero", "a", "b", "c"]
Array.isArray(ooo) // true

原型和原型链

对原型链进行操作的示例

参考:https://juejin.im/post/5a94c0de5188257a8929d837

把bark()方法放入Dog构造函数的原型中:

function Dog(name, color) {
    this.name = name
    this.color = color
}

Dog.prototype.bark = () => {
    console.log('wangwang~')
}

dog1.__proto__ === Dog.prototype // true

Dog.prototype.constructor === Dog // true

dog1.constructor === Dog // true   ==> 实例的构造函数属性(constructor)指向构造函数。

dog1对象通过Dog 构造函数创建,所以dog1的原型(dog1.__proto__)就是Dog.prototype。


 

对于原型可以归纳出下面一些点:(区分prototype和__proto__)

  • 所有的对象(包括函数对象和原型对象)都有"[[prototype]]"属性(通过__proto__访问),该属性对应对象的原型
  • 所有的函数对象都有"prototype"属性,该属性的值会被赋值给该函数创建的对象的"__proto__"属性
  • 所有的原型对象都有"constructor"属性,该属性对应创建所有指向该原型的实例的构造函数
  • 函数对象和原型对象通过"prototype"和"constructor"属性进行相互关联
  • 原型对象就是用来存放实例中共有的那部分属性。在上述例子中就是:Dog.prototype
  • 在JavaScript中,所有的对象都是由它的原型对象继承而来,反之,所有的对象都可以作为原型对象存在。
  • 访问对象的属性时,JavaScript会首先在对象自身的属性内查找,若没有找到,则会跳转到该对象的原型对象中查找。
  • 当一个函数被用作构造函数来创建实例时,该函数的prototype属性值将被作为原型赋值给所有对象实例(也就是设置实例的__proto__属性) 对象.__proto__ === 函数.prototype

var arr = [1, 2, 3];的原型链是:arr ----> Array.prototype ----> Object.prototype ----> null

函数有prototype属性的原因:

通过原型链就可以在JavaScript中实现继承。与大部分面向对象语言不同,JavaScript中并没有引入类(class)的概念,但JavaScript仍然大量地使用了对象,为了保证对象之间的联系,JavaScript引入了原型与原型链的概念。JavaScript中的所有对象都来自 Object;所有对象从Object.prototype继承方法和属性,尽管它们可能被覆盖。

JS通过new来生成对象,但是仅靠构造函数,每次生成的对象都不一样。

有时候需要在两个对象之间共享属性,由于JS在设计之初没有类的概念,所以JS使用函数的prototype来处理这部分需要被共享的属性,通过函数的prototype来模拟类:

当创建一个函数时,JS会自动为函数添加prototype属性,值是一个有constructor的对象。

 每一个实例对象都有一个私有属性_proto_,指向它的构造函数的原型对象(prototype)。原型对象也有自己的_proto_,层层向上直到一个对象的原型对象为null。这一层层原型就是原型链。

 原型链示意图 图中由相互关联的原型组成的链状结构就是原型链,也就是蓝色的这条线。

  p1和p2的原型是people.prototype,所以p1和p2都可以直接访问到新增加的age。

 查看people的prototype属性,此时新增了一个共享属性age。

不加age前仅有一个constructor

 hasOwnProperty & Object.keys()

"hasOwnProperty"是"Object.prototype"的一个方法,该方法能判断一个对象是否包含自定义属性而不是原型链上的属性


对象的创建及访问

1. 字面量对象创建

var person = {
    name: 'yibo',
    age: 22,
    hobby: ['play', 'sleep', 'eat']
    hi() {
        return 'hi I am yibo'        
    }
}

//person.name
//person.hobby[1]
//person.hi()

子命名空间:

可以用一个对象来做另一个对象成员的值。例如将name成员: 

name: {
first: 'wang',
last: 'yibo'
}

访问: person.name.first  &  person.name.last

2. 构造函数创建

构造函数创建的方式更多用来在Javascript中实现继承,多态,封装等特性。

function Animal(name) {
    this.name = name;
}
let cat = new Animal('Tom');

3. new Object()

var Person =new Object();
Person.name = 'Jason';Person.age = 21;

对象可以包含相关的数据和代码,这些代表现实世界模型的一些信息或者功能,或者它特有的一些行为. 对象数据(也经常称为函数) 可以有结构的存储 (官方术语为 封装) 在对象包内 (也可以给一个特殊的名字来表示,有时候也叫做命名空间), 可以使它容易组织和访问; 对象也通常用于存储数据,这样就可以很容易的在网络上传输.

闭包

闭包产生的目的:从外部读取局部变量。闭包的2种情况:函数作为返回值,函数作为参数传递。

闭包就是一种延缓垃圾回收的机制,一般一个函数执行完函数内部的变量会跟着销毁掉,但是有时候你还需要这个变量,为了不让这个变量被销毁掉,只要让这个变量有引用存在就行。

闭包的概念:通俗的讲就是函数a的内部函数b,被函数a外部的一个变量引用的时候,就创建了一个闭包。

 function f1(){
    var n=999;
    nAdd=function(){n+=1} // 闭包
    function f2(){
      alert(n);
    }
    return f2;
  }
  var result=f1();
  result(); // 999,闭包
  nAdd();
  result(); // 1000,闭包

闭包不会被垃圾回收机制回收,会一直保存在内存中。

闭包的最大特性就是,如果里函数引用(or访问,这俩词在这个语境下是等价的)了外函数的某个变量,那这个变量就能享受和全局变量一样的特权,不会被回收。

    (function (){
        var a = 10;
        add.onclick = function (){
            a++;
            span.innerHTML = a;
        }        
    })()    

看一下例子:https://zhuanlan.zhihu.com/p/129022735


const 常量,不可变。

let 变量,块作用域,不能重复声明覆盖。

var 变量,函数作用域,能重复声明覆盖。

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值