zoukankan      html  css  js  c++  java
  • 《JavaScript权威指南学习》学习笔记

    0.在学习之前先思考

    1. 什么是对象?
    2. 对象类型有哪一些?
    3. 对象有哪些特性?
    4. 原型是什么?
    5. 原型链是什么?
    6. 包装对象是什么?

    1. 参考资料

    《JavaScriptq权威指南》

    2.核心内容

    一、 什么是对象?

    对象是一种复合值,它将很多值(原始值或其他对象)聚合在一起,可通过属性名访问这些值。而属性名可以是包含空字符串在内的任意字符串。

    • 什么是数组?

    相同类型数据的集合

    • 什么是字典?

    字符串到值的映射

    • 什么是对象?

    对象及特殊的字典,简单理解为:字典的展示形式 + 对象的特性

    二、 对象有哪些?

    JavaScript 数据类型分为两种:

    • 原始类型:

    数字、字符串和布尔值特殊null undefined (根本区别原始值不可改变)

    • 对象类型:

    JavaScript中除了数字、字符串、布尔值、null、undefined之外的就是对象。
    数组、函数、日期、正则为特殊的对象

    三、 创建对象的方式

    1、 对象直接量

    对象直接量由若干名/值对组成的映射表,名/值对中间用冒号分隔,名/值对之间用逗号分隔,整个映射表用花括号括起来。

    var point = {x: 1, y: 2};
    var empty ={};
    var a= [];
    
    2、 通过new创建对象

     new运算符后跟随一个函数调用,即构造函数,创建并初始化一个新对象。例如:

    var o =new Object();
    var a =new Array();
    
    3、 Object.create()

      Object.create()是一个静态方法,它创建一个新对象,其中第一个参数是这个对象的原型对象,Object.create()提供第二个可选参数,用以对对象的属性进行进一步描述:

    var o1 =  Object.create({x:1,y:2});
    

    JavaScript中对象可以分为三类,对象的属性属性分为两类:

    • 内置对象(native object),例如数组、函数、日期和正则表达式;
    • 宿主对象(host object),即JavaScript解释器所嵌入的宿主环境定义的;
    • 自定义对象(user-defined object),是由运行中的JavaScript代码创建的对象;

    对象的属性可以分为两类:

    • 自有属性(own property):直接在对象中定义的属性;
    • 继承属性(inherited property):在对象的原型对象中定义的属性;

    四、 对象有哪些特性?

      每个对象都有与之相关的原型(prototype)、类(class)和可扩展性(extensible attribute)

    1. 原型特性

    基本上每一个JavaScript对象都和另一个对象相关联,“另一个”对象就是所谓的原型对象。每一个对象都从原型对象继承属性,并且一个对象的prototype属性的值就是这个对象的原型对象。
    JavaScript语言规定了:

    • 所有通过对象直接量创建的对象的原型对象就是Object.prototype对象;
    • 通过关键字new和构造函数创建的对象的原型对象就是构造函数prototype属性的值,所以通过构造函数Object创建的对象的原型就是Object.prototype了;
        
    Object.create(null);
    
    

    那么,如何查询一个对象的原型属性呢?将对象作为参数传入Object.getPrototypeOf()可以查询它的原型
    要检测一个对象是否是另一个对象的原型(或处于原型链中),可以使用isPrototypeOf()方法。

    Object.getPrototypeOf(o);
    a.isPrototypeOf(b);
    

    还有一个非标准但众多浏览器都已实现的对象的属性__proto__(同样是两个下划线开始和结束,以表明其为非标准),用以直接查询/设置对象的原型。

    2. 类属性

    对象的类属性(class attribute)是一个字符串,用以表示对象的类型信息。

    function classof(o){
        if(o === null){
            return 'Null';
        }
        if(o === undefined){
            return 'Undefined';
        }
        return Object.prototype.toString.call(o).slice(8, -1);
    }
     
    var a1= new Array();
    var b1= new Date();
    var c1= new Date();
    var a = classof(a1);
    var b = classof(b1);
    var c = classof(c1);
    
    3. 可扩展性

      对象的可扩展性用以表示是否可以给对象添加新属性。所有内置对象和自定义对象都是显示可扩展的,宿主对象的可扩展性是由JavaScript引擎定义的。相关函数:

    • 1 通过将对象传入Object.isExtensible(),来判断该对象是否是可扩展的。
    • 2 如果想将对象转换为不可扩展,需要调用Object.preventExtensions(),将待转换的对象作为参数传进去。
      注意:
      a.一旦将对象转换为不可扩展的,就无法再将其转换回可扩展的了;
      b.preventExtensions()只影响到对象自身的可扩展性,如果给一个不可扩展的对象的原型添加属性,这个不可扩展的对象同样会继承这些新属性;

        

    Object.seal()和Object.preventExtensions()类似,除了能将对象设置为不可扩展的,还可以将对象的所有自有属性都设置为不可配置的。(对于那些已经封闭(sealed)起来的对象是不能解封的);可以使用Object.isSealed()来检测对象是否封闭。

    更进一步,Object.freeze()将更严格地锁定对象——“冻结”(frozen)。除了将对象设置为不可扩展和将其属性设置为不可配置之外,还可以将它自有的所有数据属性设置为只读(若对象的存取器属性有setter方法,存取器属性将不受影响,仍可通过给属性赋值调用它们)。使用Object.isFrozen()来检测对象是否总结。

    Object.isExtensible();
    Object.isSealed();
    Object.isFrozen();
    
    //将对象设置为不可扩展
    Object.preventExtensions();
                
    //将对象设置为不可扩展,并将对象自有属性设置为不可配置
    Object.seal();
                
    //将对象设置为不可扩展,并将对象自有属性设置为不可配置、不可写
    Object.freeze();
    
    

    五、 属性的特性

    1.存取器属性

    上面我们所说的都是很普通的对象属性,这种属性称做“数据属性”(data property),数据属性只有一个简单的值。然而在ECMAScript 5中,属性值可以用一个或两个方法替代,这两个方法就是getter和setter,有getter和setter定义的属性称做“存取器属性”(accessor property)。

    当程序查询存取器属性的值时,JavaScript调用getter方法(无参数)。这个方法的返回值就是属性存取表达式的值。当程序设置一个存取器属性的值时,JavaScript调用setter方法,将赋值表达式右侧的值当做参数传入setter。如果属性同时具有getter和setter方法,那么它就是一个读/写属性;如果它只有getter方法,那么它就是一个只读属性,给只读属性赋值不会报错,但是并不能成功;如果它只有setter方法,那么它是一个只写属性,读取只写属性总是返回undefined。看个实际的例子:

    var p = {
         x: 1.0,
         y: 2.0,
         get r(){ return Math.sqrt(this.x*this.x + this.y*this.y); };
         set r(newvalue){
             var oldvalue = Math.sqrt(this.x*this.x + this.y*this.y);
             var ratio = newvalue/oldvalue;
             this.x *= ratio;
             this.y *= ratio;
         },
         get theta(){ return Math.atan2(this.y, this.x); },
       print: function(){ console.log('x:'+this.x+', y:'+this.y); }
    };
    

      正如例子所写,存取器属性定义一个或两个和属性同名的函数,这个函数定义并没有使用function关键字,而是使用get和set,也没有使用冒号将属性名和函数体分隔开。对比一下,下面的print属性是一个函数方法。注意:这里的getter和setter里this关键字的用法,JavaScript把这些函数当做对象的方法来调用,也就是说,在函数体内的this指向这个对象
     
      正如控制台的输出,r、theta同x,y一样只是一个值属性,print是一个方法属性。ECMAScript 5增加的这种存取器,虽然比普通属性更为复杂了,但是也使得操作对象属性键值对更加严谨了。

    2.属性的特性

    对象属性是由名字和值跟一组属性特性构成的,属性值可以用一个或两个方法进行替代,这两个方法就是getter和setter定义的属性特性。由getter和setter定义的属性叫做“存取器属性”。
     
      
    在这里我们将存取器属性的getter和setter方法看成是属性的特性。按照这个逻辑,我们也可以把属性的值同样看做属性的特性。因此,可以认为属性包含一个名字和4个特性。数据属性的4个特性分别是它的值(value)、可写性(writable)、可枚举性(enumerable)和可配置性(configurable)。存取器属性不具有值特性和可写性它们的可写性是由setter方法是否存在与否决定的。因此存取器属性的4个特性是读取(get)、写入(set)、可枚举性和可配置性。
      
      
      为了实现属性特性的查询和设置操作,ECMAScript 5中定义了一个名为“属性描述符”(property descriptor)的对象,这个对象代表那4个特性。描述符对象的属性和它们所描述的属性特性是同名的。因此,数据属性的描述符对象的属性有value、writable、enumerable和configurable。存取器属性的描述符对象则用get属性和set属性代替value和writable。其中writable、enumerable和configurable都是布尔值,当然,get属性和set属性是函数值。通过调用Object.getOwnPropertyDescriptor()可以获得某个对象特定属性的属性描述符:

    Object.getOwnPropertyDescriptor({x:1},"x");
    Object.getOwnPropertyDescriptor({},"x");
    Object.getOwnPropertyDescriptor({},"toString");
    
    

      从函数名字就可以看出,Object.getOwnPropertyDescriptor()只能得到自有属性的描述符,对于继承属性和不存在的属性它都返回undefined。要想获得继承属性的特性,需要遍历原型链(Object.getPortotypeOf())。
      
      要想设置属性的特性,或者想让新建属性具有某种特性,则需要调用Object.definePeoperty(),传入需要修改的对象、要创建或修改的属性的名称以及属性描述符对象:

    Object.defineProperty(o,"x",{value:1,writable:true,enumerable:false,configurable:true})
    
    Object.x;
    Object.keys(o); // => []; 
    
    Object.defineProperty(o,'x',{writable:false});
    o.x = 2;
    o.x;
    
    //test  可配置与可写
    // object.defineProperty();
    
    

    六、 属性的查询和设置

      可以通过点(.)或方括号([])运算符来获取和设置属性的值。

    原型链

      概述中说过,JavaScript对象具有”自有属性“,也有“继承属性”。当查询对象obj的属性x时,首先会查找对象obj自有属性中是否有x,如果没有,就会查找对象obj的原型对象obj.prototype是否有属性x,如果没有,就会进而查找对象obj.prototype的原型对象obj.prototype.prototype是否有属性x,就这样直到找到x或者查找到的原型对象是undefined的对象为止。可以看到,一个对象上面继承了很多原型对象,这些原型对象就构成了一个”链“,这也就是我们平时所说的“原型链”,这种继承也就是JavaScript中“原型式继承”(prototypal inheritance)。
      
      对象o查询某一属性时正如上面所说会沿着原型链一步步查找,但是其设置某一属性的值时,只会修改或新增自有属性,并不会修改原型链上其他对象的属性。

    七、 删除属性

      delete运算符可以删除对象的属性,它的操作数应该是一个属性访问表达式。但是,delete只是断开属性和宿主对象的联系,而不会去操作属性中的属性(内存泄露):

    var a = {p:{x:1}};
    var b = a.p;
    delete a.p;
    // test 
    
     delete只能删除自有属性,
    
    1 var obj = {x: 1} 
    delete obj.x;     //删除对象obj的属性x,返回true
    delete obj.x;    //删除不存在的属性,返回true
    delete obj.r;    //删除对象obj的属性r,返回true
    delete obj.toString;   //没有任何副作用(toString是继承来的,并不能删除),返回true
    delete 1;  //数字1不是属性访问表达式,返回true
    

      delete表达式返回true的情况:

    •     删除成功或没有任何副作用(比如删除不存在的属性)时;
    •     如果delete后不是一个属性访问表达式;

      delete表达式返回false的情况:

    •     删除可配置性(可配置性是属性的一种特性,下面会谈到)为false的属性时;
    delete Object.prototype;     //返回false,prototype属性是不可配置的
    //通过var声明的变量或function声明的函数是全局对象的不可配置属性
    var x = 1;
    delete this.x;     //返回false
    function f() {}
    delete this.f;    //返回false
    

    八、 检测属性
      检测一个对象的属性也有三种方法,下面就来详细说说它们的作用及区别!

    1.in运算符

      in运算符左侧是属性名(字符串),右侧是对象。如果对象的自有属性或继承属性中包含这个属性则返回true,否则返回false。

    2.hasOwnProperty()

      对象的hasOwnProperty()方法用来检测给定的名字是否是对象的自有属性(不论这些属性是否可枚举),对于继承属性它将返回false。

    3.propertyIsEnumerable()

      propertyIsEnumerable()是hasOwnProperty()的增强版,只有检测到是自有属性且这个属性可枚举性为true时它才返回true。

    var o = {
        value: 1,
        b: 2,
        c: 3
     };
    
    var x = 'b' in o;
    var x1 = o.hasOwnProperty('b');
    var x2 = o.propertyIsEnumerable('b');
    

    九、 枚举属性

     相对于检测属性,我们更常用的是枚举属性。枚举属性我们通常使用for/in循环,它可以在循环体中遍历对象中所有可枚举的自有属性和继承属性,把属性名称赋值给循环变量。

    Object.getOwnpropertyNames();//它返回对象的所有自有属性的名称,不论是否可枚举;
    
    Object.keys(); //它返回对象对象中可枚举的自有属性的名称;
    
    
    for(var c in o){
      console.log(o[c]);
    }
    var m = o.propertyIsEnumerable('toString');
    Object.getOwnpropertyNames(o);
    Object.keys(o);
    

    3.总结

    开头说的问题在本文中大部分都能找到答案,唯独最后一个问题“什么是包装对象?”
    接下来先看一段代码

    var s ="hello world!";
    var word = s.substring(s.indexOf(" ")+1,s.length);
    

    这段代码看起来似乎很正常,但是疑问点就在于,上文说到字符串类型是原始类型怎么会有方法呢?原来:只要引用了字符串s的属性,JavaScript就会将字符串值通过调用new String(s)的方式转换成对象,这个对象继承了字符串的方法,并被用来处理属性的引用。一旦属性引用结束,这个新创建的对象就会销毁...

    存取字符串、数字或布尔值的属性时创建的临时对象称做包装对象

    欢迎大家批评指正,共同学习,共同进步!
    作者:Iannnnnnnnnnnnn
    出处:https://www.cnblogs.com/Iannnnnnnnnnnnn
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
  • 相关阅读:
    Windows10系统下在Docker中部署静态网站
    NET接入Mesher--------解决微服务什么时候能支持.net 的应用开发的问题
    Windows系统下 ASP.NET Core 的 Docker 映像创建
    Windows平台部署 Asp.Net Core 3.1.0,将 ASP.NET Core 应用发布到 IIS ,使用 IIS 在 Windows 上托管 ASP.NET Core
    如何使用Activator.CreateInstance创建一个列表<T>,其中T在运行时是未知的?
    在 Visual Studio 中安装 FxCop 分析器
    .Net Core3.1下使用Swagger搭建web api项目
    Vuex访问状态对象的方法
    Vuex最基本样例
    搜索框 展示相关搜索内容列表,及延迟改进(仿百度)
  • 原文地址:https://www.cnblogs.com/Iannnnnnnnnnnnn/p/14433522.html
Copyright © 2011-2022 走看看