Javascript语言精粹学习笔记之对象(简单数据类型不是对象!)

一、引入


  对于丑陋的事物,爱会闭目无视。  - 威廉·莎士比亚《维洛那二绅士》

Javascript的简单类型包括

  1.数字number(JS不分整形和浮点型,两个浮点型相加,精度不够,计算的结果不正确)

let num1 = 1,
    num2 = 2.1;
    console.log(typeof num1);	//结果为number
	console.log(typeof num2);	//结果为number
	console.log(num2+0.2);		//结果为2.3000000000000003

  2.字符串string
  3.布尔值boolean
  4.null
  5.undefined
  6.symbol
  以上类型都是简单数据类型,其他都是对象,数组是对象,函数是对象,正值表达式是对象,对象自然也是对象。



简单数据类型不是对象

    发现书中有一句话 "前五个貌似是对象,因为他们拥有方法,但是他们是不可变的?"
    那么简单数据类型,不是对象嘛?明显不是,只有复杂数据类型是对象。

  两者的不同点:
    1.基本类型没有附加方法; 所以你永远不会看到undefined.toString()。 也正因为如此,基本类型是不可变的,因为它们没有附加的方法可以改变它:

var s = "zs";
s.bar = "ls";
console.log(s.bar); // 输出 undefined

    而默认情况下,对象是可变的,可以添加方法:

var obj = {};
obj.num = 88;  
console.log(obj.num); // 输出 88  

    2.与作为引用存储的对象不同,基本类型作为值本身存储。 这在执行相等性检查时会产生影响:

"zs" === "zs"; // 输出 true
1 === 1; // 输出 true
 
[] === []; // 输出 false
(function () {}) === (function () {}); // 输出 false

    基本类型按值存储,对象通过引用存储,存储地址也不同,基本类型直接存放在栈中,而对象是存放在堆里的

  临时包装:

    原始字符串和对象的构造函数都是String函数。 但是你可以在原始字符串上调用.constructor这个方法,可是基本类型不是不能有方法,为什么呢?先看下面的代码:

var pet = new String("zs")
pet.constructor === String; // 输出 true
String("zs").constructor === String; // 输出 true

    上面代码所发生的事情是一个叫做Auto-Boxing的过程,当你尝试在某些基本类型上调用属性或方法时,JavaScript首先将其转换为临时包装器对象,并访问其上的属性/方法,而不会影响原始属性。

var pet = "zs";
console.log(pet.length); // 输出 2
pet === "zs"; // 输出 true

    在上面的代码中,要访问属性length,JavaScript发生临时包装过程将pet转换为包装器对象,访问完包装器对象的length属性,然后将其丢弃。 这样做不会影响pet(pet仍然是一个原始字符串)。

    这也解释了为什么JavaScript在尝试将属性分配给基本类型时不会出问题,因为赋值是在该临时包装器对象上完成的,而不是基本类型本身,比如:

var foo = 23;
foo.bar = "zs"; // 是在临时包装器对象上完成的赋值
foo.bar; // 输出 undefined

    但原始类型undefined和null,都是没有包装器对象的,当你尝试赋予属性时,它会报错。

var foo = null;
foo.bar = "zs"; // Uncaught TypeError: Cannot set property 'bar' of null




对象的其他概念

  • 对象是属性的容器,其中每个属性都拥有名字和值。属性的名字可以是包括空字符串在内的任意字符串。属性值可以是除undefined值之外的任何值。

  • JavaScript 中的对象是无类别(class-free)的。它对新属性的名字和值没有约束。对象适合用于收集和管理数据。对象可以包含其他对象。

  • JAvaScript 包括一个原型链特性,允许对象继承另一个对象的属性。







二、对象


2.1 对象字面量

  对象字面量可以理解为创建 新对象值的 表示法。
  一个对象字面量就是 包围在一对花括号 中的 零或多个“名/值”对
  对象字面量可以出现在任何允许表达式出现的地方。

var empty_object = {};
    
    var object = {
        "first_name": "zhang",
        "last-name": "san"
    };

  属性名可以是包含空字符串在内的任意字符串。在对象字面量中,若属性名合法标识符(非保留字),则不强制要求用引号括住属性名,所以上文first_name 下划线标准写法中引号可以省略,而 last-name 减号的""必须有。
  并且,对象可嵌套,如下:

var father = {
  name: "zs",
  age: "22",
  son: {
    first: "ls",
    second: "cucumber",
  },
};

2.2 检索

  要检索对象里包含的值,可用以[ ]表达式,若字符串是合法标识符而非保留字,则也可用 . 调用,常规下,优先使用紧凑且可读性好的 . 调用。

father.name; //"zs"
father["name"]; //"zs"

  若尝试检索不存在的成员属性值,则返回undefined

father.people; //undefined
father["people"]; //undefined

  利用运算符||可以进行默认值填充:

let dear = father.people || "none"; //none
let gender = father.gender; //undefined

3.3 更新

  对象中的值可以通过赋值来进行更新,若属性名已经存在,那么这个属性会被覆盖掉。

var father = {
  name: "zs",
  age: "22",
  son: {
    first: "ls",
    second: "cucumber",
  },
};
console.log(father.age); //22
father.age = 23;
console.log(father.age); //23

  若该对象之前没有拥有该属性名,则会被扩充到此对象中。

  father.city='HangZhou';
{name: "zs", age: 23, son: {}, city: "HangZhou"}

3.4 引用

  对象通过引用来传递。它们永远不会被拷贝:
    box2指向同一个对象引用,因此共享属性

var box1={
    check:'book',
  }
  var box2=box1;
  box1.price='300元';
  console.log(box1.price);//300元
  console.log(box2.price);//300元

    x、y、z 它们每个都引用了不同的对象,因此也各不影响

var x = {},
  y = {},
  z = {};
x == y; //false
var a = (b = c = {});
a === b; //true

3.5 原型

  每个对象都关联到一个原型对象,并可从中继承相应属性。所有通过对象字面量创建的对象都连接到 Object.prototype,它也是 JavaScript 中的终点对象
  当创建一个新对象时,可以选择某个对象为其原型,可以尝试给 Object 添加一个 create 方法,它可以创建一个使用原对象作为其原型的新对象。

var box1={
    check:'book',
    checkbox:{
      check:'pencil',
      price:'300元'
    },
    getPrice:function(){
      return '250元'
    }
  }
if(typeof Object.beget!=='function'){
  Object.create=function(o){
    var F=function(){};
    F.prototype=o;//使其原型改为传进来的对象
    return new F();
  }
}
var goodsInfo=Object.create(box1)
console.log(goodsInfo.check)//'book'
console.log(goodsInfo.getPrice())//'250元'

  原型连接在更新时是不起作用的。当我们对某个对象做出改变是,不会触及到该对象的原型:

goodsInfo.check = 'Harry';
console.log(goodsInfo.check);//Harry
console.log(box1.check);//book

  原型连接只有在检索值的时候才被用到。如果我们尝试去获取对象得某个属性值,且该对象没有此属性名,那么JavaScript会试着从原型对象中获取属性值。如果那个原型对象也没有该属性,那么再从它的原型中寻找,以此类推,直到该过程最后到达终点Object.prototype。如果想要得属性完全不存在于原型链中,那么结果就是 undefined值。这个过程称为委托。
  原型关系是一种动态的关系。如果我们添加一个新的属性到原型中,该属性会立即对所有基于该原型创建的对象可见。

box1.check = 'zs';
console.log(goodsInfo.check); //zs

3.6 反射

  检查并确定对象具有的属性,只有进行检索并验证即可,通常使用typeof

typeof box1.check; //"string"
typeof box1.checkbox; //"object"
typeof box1.getPrice; //"function"

  原型链
  但原型链中的任何属性还会产生同一个值constructor,例如:

typeof box.toString; //'function'
typeof box.constructor; //'function'

  为了处理掉这些不需要的属性,可以换种方法来验证,比如利用hasOwnProperty
  它用来检验是否是对象独有的属性,它将返回对应的布尔值,它不会检查原型链

box1.hasOwnProperty("check"); //true
box1.hasOwnProperty("getcheck"); //false

3.7 枚举

  for in 语句用来遍历对象中的所有属性名。该枚举过程会列出所有的属性(包括函数和原型链中的属性)
  同时一般利用 typeof 来排除不想要的函数

var box1 = {
  check: "book",
  checkbox: {
    check: "pencil",
    price: "300元",
  },
  getPrice: function () {
    return "250元";
  },
};

for (name in box1) {
  if (typeof box1[name] !== "function") {
    console.log(name + ":" + box1[name]);
    //check:book
    //checkbox:[object Object]
  }
}

  因为属性名出现的顺序具有不确定性,因此要对可能出现的顺序有所准备
  若想避免这种不确定性出现,那么应避免出现for in语句,转而换为数组循环

var box1 = ["book", "pencil", "300元"];

for (let i = 0; i < box1.length; i++) {
  console.log(box1[i]);
}

3.8 删除

  delete 运算符可以用来删除某对象的属性,若此对象含有该属性,则移除(不会对原型链中的对象产生影响)
  删除某对象的属性,可能会让它原型链中的此属性表现出来
  若原型链 object 上有 a 属性,而对象 A 身上也有 a 属性,则 A 使用时以自身为准
(这也是为什么,删除 A 身上的 a 属性时,A 身上的 object 的 a 属性生效的原因)如下:

function Play1() {}
Play1.prototype = {
  constructor: Play1,
  name: "proto",
  sex: "boy",
  hobby: "coding",
};
var Play2 = new Play1();
Play2.hobby = "打王者";
console.log(Play2.hobby); //'打王者'
delete Play2.hobby;
console.log(Play2.hobby); //'coding'

3.9 减少全局变量污染

  JavaScript可以随意定义全局变量(当然,这在方便的同时带来很多隐患)
  为降低这些隐患,一般为其应用创建唯一全局变量容器
  把全局资源都归纳至一个名称空间下,则会显著降低命名冲突。

var boxs = {};
boxs.content = {
  first_box: "tomato",
  second_box: "cucumber",
  third_box: "potato",
};
boxs.price = {
  tomato: "25",
  cucumber: "15",
  potato: "10",
};







三、总结:

  本章节描述的是在JavaScript语言中的对象的基本概念。

  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
### 回答1: "JavaScript语言精粹"是一本由Douglas Crockford撰写的著名图书,是许多JavaScript开发者学习与掌握该语言不可或缺的重要资源。 这本书主要关注于JavaScript的核心概念和最佳实践,帮助开发者摆脱一些语言的怪异之处和陷阱,使其能够更加高效地编写可维护和可扩展的代码。 "JavaScript语言精粹"一书将JavaScript的精华提炼为19个章节,每一章节都深入浅出地介绍了一个关键概念,包括函数、对象、数组、代码风格、错误处理等。作者以清晰简洁的语言解释了这些概念的背后原理,并给出了许多实用的代码示例。 这本书不仅适合JavaScript初学者,对于有一定经验的开发者来说也是一本不可多得的参考书。通过阅读它,开发者可以拓宽对JavaScript的理解和认识,提高代码质量和效率。 除了对基础概念的详细介绍外,"JavaScript语言精粹"还包含了一些进阶话题,如闭包、原型链、模块化等,帮助开发者进一步提升其JavaScript编程能力。 总之,"JavaScript语言精粹"是一本权威而实用的JavaScript学习资源,对于想要深入理解和掌握该语言的人来说是极为重要的一本书籍。无论你是初学者还是有经验的开发者,这本书都能帮助你写出更优雅、可读性更高的JavaScript代码。 ### 回答2: 《JavaScript语言精粹》是一本由Douglas Crockford撰写的权威指南,它介绍了JavaScript语言中最重要和最有用的部分。该书通过简洁而清晰的语言讲解了JavaScript的核心概念和特性,为开发者提供了深入理解和运用JavaScript的方法和技巧。 这本书以独特的方式展现了JavaScript的精华,将复杂的语法和概念简化成易于理解和运用的形式。Crockford首先介绍了JavaScript中的基本语法和数据类型,然后深入讲解了函数、对象、原型、闭包等重要概念。他通过具体的示例和练习,引导读者掌握JavaScript中的核心概念和编程技巧。 《JavaScript语言精粹》还包含了对常见错误和陷阱的警示,帮助读者避免在编写JavaScript代码时常见的问题。此外,该书还提供了一些最佳实践和编码规范,帮助开发者写出高质量、可维护的JavaScript代码。 与其他JavaScript教程不同,《JavaScript语言精粹》不仅关注如何正确地使用JavaScript,还强调了一些可以帮助开发者避免错误和提高代码质量的技巧和原则。这使得这本书成为了一本适合初学者和有经验的开发者阅读的权威指南。 总之,《JavaScript语言精粹》是一本深入而全面地介绍JavaScript语言的书籍。无论你是初学者还是有经验的开发者,阅读这本书都可以帮助你建立起对JavaScript的深入理解,并提高你的JavaScript编程技巧。 ### 回答3: 《JavaScript语言精粹》是一本由Douglas Crockford所著的程序设计相关书籍,它主要介绍了JavaScript语言的核心概念和重要知识点。这本书在程序设计领域有着很高的声誉,被许多程序员视为JavaScript编程的经典参考书。 该书的目的是帮助读者深入理解JavaScript语言的精华部分,将复杂的语法和特性解释得简单易懂。它详细介绍了JavaScript的基本数据类型、函数、对象、原型链以及闭包等重要概念,并提供了一些实用的编程技巧和最佳实践。读者通过学习这些内容,可以更好地理解JavaScript的设计哲学和编程范式。 《JavaScript语言精粹》的内容不仅限于语法的讲解,还包括了一些关于代码风格、错误处理和性能优化等方面的建议。它强调代码的可读性、可维护性和可扩展性,帮助读者编写出高质量的JavaScript代码。 这本书的另一个亮点是作者Douglas Crockford的独特见解和深入思考。他不仅仅是介绍了JavaScript的特性,还对其设计和演变进行了深入的分析和比较。他提出了一些有关编程规范和标准化的建议,为读者在实际开发中避免一些常见的陷阱和错误提供了宝贵的经验。 总之,《JavaScript语言精粹》是一本经典的JavaScript编程参考书籍,适合有一定编程基础的读者阅读。它能够帮助读者深入理解JavaScript的核心概念和设计原理,提高编程技巧,写出高质量的代码。无论是初学者还是有经验的开发者,都会从这本书中获益匪浅。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值