• 从JS库的使用者转变成JS的开发者——第一篇 javascript对象


    此文是《Javascript Elightment》的读书笔记,希望和有意向从jS库的使用者转变成js的开发者的童鞋们一起分享。

    第一篇  javascript 对象

    创建对象

    Js中,所有事物都是对象或者可以表现得像对象

    记住:对象事实上就是一个属性(名字和对应的值)的容器

    方法其实也是对象的一个属性,它包含了用来操作对象的function()对象。如果没有方法,对象除了保存静态属性外什么也做不了

    创建一个对象:var myObject = new Object();

    上面代码解析: 我们用一个指向Object() 构造函数的空对象去创建新对象。

    可以把构造函数看成生产预定义好的对象的模板

    我们也可以自己创建一个对象构造函数,用来大量“生产”我们需要的对象。

    如:

    var Person = function(living, age, gender) {

    this.living = living;

    this.age = age;

    this.gender = gender;

    this.getGender = function() {return this.gender;};

    };

    var cody = new Person(true, 33, 'male');

    js 构造函数构建和返回对象实例

    构造函数的作用是创建一批共享特定属性和方法的对象

    构造函数在正常时候不外乎是一个函数,但是当被new调用后,这个函数就被特殊对待,因为它要设置正准备创建的对象的属性值,然后返回一个建好的对象,这个对象就被认作这个构造函数构造出来的实例。

    Js 原生/内置对象(Native/Built-In Object)的构造函数

    Js的9个原生对象:

    • Number()

    • String()

    • Boolean()

    • Object()

    • Array()

    • Function()

    • Date()

    • RegExp()

    • Error()

    自定义构造函数

    自定义的构造函数名字的首字母最好大写

    在创建对象的时候可以省去new关键字,但是在定义构造函数的时候必须明确地返回一个对象。

    如:

    var myFunction = function(){return {prop: val}};

    上面的做法避免了prototype的继承

    用new实例化构造函数

    new操作就是告诉js解释器——我们要建一个相应的构造函数的实例

    Math()

    Math与其它内置构造函数不一样,它是一个静态对象,并不是构造函数,所以不能用new来构建一个实例,但是你可以用它已经建好的实例(如 Math.PI)。事实上Math只是js用来存储math方法的一个对象。

    注意: Math 是一个静态对象(一个包含其它方法的容器),不可以用new操作。

    用构造函数创建速记/字面值(Shorthand/Literal Values)

    Js提供了“字面值”的快捷方式去制造大多数的内置对象值,所以我们不需要每次都用new操作

    大多数情况字面值方式和new操作做的事是一样的除了Number(),String()和Boolean().

    如:

    var myObject = new Object();
    var myObjectLiteral = {};

    var myNumber = new Number(23);

    var myNumberLiteral = 23;

    注意: 用字面值创建string, number, boolean对象,刚开始并不是创建一个真正的复杂的对象,而是单纯的一个原始数据类型,只有当这个对象被当做对象用(调用构造函数内的方法,获取属性)时,js才会为这个字面值创建一个封装对象,允许这个字面值像对象一样操作,当构造函数内的方法调用完后,js就会抛弃这个对象,字面值又恢复成单纯的数据类型。(这里解释了为什么“js里所有的事物都是对象或可以像对象一样操作”)。

    原始值(Primitive Values) null,undefined,“string”,10,true,false都不是对象

    原始值不是对象,它们只是用来表示简单的值。

    原始值如何在js中储存和复制

    原始值的储存和操作仅限于数值表面的,不可还原的。

    var myString = 'foo' // create a primitive string object

    var myStringCopy = myString; // copy its value into a new variable

    var myString = null; // manipulate the value stored in the myString variable

    /* The original value from myString was copied to myStringCopy. This is confirmed

    by updating the value of myString then checking the value of myStringCopy */

    console.log(myString, myStringCopy); // logs 'null foo'

    原始值的对比

    如果不是通过new创建的对象,那么原始值的类型还是原始类型。如果用new创建对象,即使数值相同,但是类型已经不再是原始类型了,而变成了对象

    var price1 = 10;
    var price2 = 10;
    var price3 = new Number('10'); // a complex numeric object because new was used
    var price4 = price3;
    console.log(price1 === price2); // logs true
    /* logs false because price3 contains a complex number object and price 1 is
    a primitive value */
    console.log(price1 === price3);
    // logs true because complex values are equal by reference, not value
    console.log(price4 === price3);
    // what if we update the price4 variable to contain a primitive value?
    price4 = 10;
    console.log(price4 === price3); /* logs false: price4 is now primitive
    rather than complex */

    复合值(Complex Values)

    内置对象 Object(),Array(),Function(),Date(),Error(),RegExp()都是复合值,因为它们包含一个或多个原始值和复合值

    复合值在js中如何存储和复制

    新创建一个对象后,这个对象会被储存在内存的某个地址里;当你调用这个对象时,你用对象的名字去获得内存地址里的值

    对象的复制并不是像原始值一样单纯在数值表面的复制,复制的是对象的引用值/地址值,并不是真的数值,这意味着对象并不是完全被复制。所以,复制的对象和源对象其实指向同一个地址值,即它们操作的是同一个对象

    var myObject = {};

    var copyOfMyObject = myObject; /* not copied by value,

    just the reference is copied */

    myObject.foo = 'bar'; // manipulate the value stored in myObject

    /* Now if we log myObject and copyOfMyObject, they will have a foo property

    because they reference the same object. */

    console.log(myObject, copyOfMyObject); /* logs 'Object { foo="bar"}Object { foo="bar"}' */

    注意: String(),Number(),Boolean()被new创建或偷偷被临时转成对象,这些值任然是以单纯的数值表面存储和复制。所以即使原始值可以做类似对象一样的操作,它们的存储复制方式也不会和对象一样

    如果想完全复制一个对象,那就必须把源对象里的值获取出来并注入新的对象中

    复合值的对比

    只有当两个对象指向的是同一个对象,即有相同的存储地址时,两个对象才是相等的。否则,即使两个对象看上去完全一样,它们也是不等的。

    var objectFoo = {same: 'same'};

    var objectBar = {same: 'same'};

    /* logs false, JS does not care that they are identical

    and of the same object type */

    console.log(objectFoo === objectBar);

    // how complex objects are measured for equality

    var objectA = {foo: 'bar'};

    var objectB = objectA;

    console.log(objectA === objectB); /* logs true because they reference

    the same object */

    复合对象的动态属性

    已经知道,一个变量指向一个现有的对象时并不是复制这个对象,仅仅是复制了对象的地址。所以一个对象可以拥有很多个引用对象,它们都指向同一个地址的源对象。

    所以,只要这些对象中任意一个的属性改动,则其它的对象都会一起改动

    原始值和复合值的typeof 操作

    值的类型要根据环境来确定。如下面,除了用new操作创建的对象外,其它快捷创建出来的值都是原始类型

    var myNull = null;

    var myUndefined = undefined;

    var primitiveString1 = "string";

    var primitiveString2 = String('string');

    console.log(typeof myNull); // logs object? WHAT? Be aware...

    console.log(typeof myUndefined); // logs undefined

    console.log(typeof primitiveString1, typeof primitiveString2);// logs string string

    // Complex Values

    var myNumber = new Number(23);

    var myString = new String('male');

    var myBoolean = new Boolean(false);

    console.log(typeof myNumber); // logs object

    console.log(typeof myString); // logs object

    console.log(typeof myBoolean); // logs object

    对象的可变性

    因为对象拥有动态属性的特点,导致了它是可变的,即使是js的内置对象。这意味着你可以随时随地改变js中的大多数对象,改变它原配置的属性,添加属性方法等(实际上这种做法是不推荐的)。

    所有的构造函数实例都有指向它们的构造函数的构造函数属性

    每个实例都有一个构造函数属性,这个属性指向了构造这个实例的构造函数。

    即使是原始值,也同样拥有构造函数属性,但是构造出来的并不是对象,仍是一个原始值。

    var myNumber = new Number('23');

    var myNumberL = 23; // literal shorthand

    var myString = new String('male');

    var myStringL = 'male'; // literal shorthand

    console.log( // all of these return true

    myNumber.constructor === Number,

    myNumberL.constructor === Number,

    myString.constructor === String,

    myStringL.constructor === String);

    如果希望自定义的对象的构造函数有确切的名字,则在定义的时候要先给它命名。如

    var Person = function Person(){};

    每个对象都是特定的构造函数的实例

    instranceof() 函数可以用来判断一个对象是否是某个构造函数的实例。

    注:1. 每个对象都是Object()构造函数的实例

          2. 如果原始值不是new出来的,则在判断构造函数实例时一定会返回false. (e.g., 'foo' instanceof

    String // returns false).

    构造函数构造的实例可以拥有它们独立的属性

    Js中,对象随时可以被扩展。但是原始值不可以进行扩展

    var myString = new String();

    var myNumber = new Number();

    myString.prop = 'test';

    myNumber.prop = 'test';

    console.log(myString.prop,myNumber.prop); // logs 'test', 'test'

    // be aware: instance properties do not work with primitive/literal values

    var myString = 'string';

    var myNumber = 1;

    myString.prop = true;

    myNumber.prop = true;

    // logs undefined, undefined

    console.log(myString.prop, myNumber.prop);

    注: 除了构造函数的属性外,实例还会从prototype 链继承属性。如上所述,实例也可拥有自己扩展的属性。

    “Javascript Objects” 和 “Object() Objects” 语义上的区别

    Javascript Objects 泛指js中的所有对象,Object() Objects特指由Object构造函数构造出来的名字为Objects的对象

    后面会继续更新”第二篇 使用对象和属性“。

    此文为原创,转载请附链接,谢谢。

  • 相关阅读:
    javascript typeof 和 instanceof 的区别和联系
    || and && 理解
    jquery选择器总结
    overflow-y:auto 回到顶部
    HTML 获取屏幕,浏览器,页面的高度
    height()、innerHeight()、outerHeight()函数的区别详解
    git入门篇-----本地操作
    sublime快捷键
    Atom 和 VSCode 同一天发布神器:实时编码分享
    编辑器插件和配置备份神器--sync setting
  • 原文地址:https://www.cnblogs.com/liubingna/p/2978234.html
Copyright © 2020-2023  润新知