[TOC]
****
## 0 意義
Object(對象)是js中內置對象之一。可以將對象看成鍵值數據結構。
鍵值對中的鍵稱為對象的屬性只能是數字或者字符串
鍵值對中的值可以是任意其他類型
除了null和undefined,其他所有的都可以轉換為對象
## 1 簡單例子
### 1-2 對象的引用使用
~~~
var studenA = {
name:"sundway"
}
var studentB = studentA;
studentB.name = "modify";
console.log(studentA.name); //"modify"
console.log(studentB.name); //"modify"
//studentA和studentB同時是對內存中的一個引用。修改其中的一個值會影響另一個
~~~
### 1-2 對象的屬性只能是字符串或者數字
~~~
var studentA = {
"name" : "sundway"
}
var studentA = {
1 : "sundway
}
console.log(studentA[1]); //輸出"sundway"
//屬性為數字時,不能使用.運算符讀取屬性值,只可以使用[]讀取屬性值
~~~
### 1-3 除了null和undefined轉換到對象
~~~
2.toString(); // Uncaught SyntaxError
2..toString(); // the second point is correctly recognized
2 .toString(); // note the space left to the dot
(2).toString(); // 2 is evaluated first
~~~
## 2 對象屬性
### 2-1 屬性描述
屬性描述符:包含數據描述符和存儲描述符
數據描述符(configurable,enumerable,value,writable)
數據描述符實現對數據可寫或不可寫值的屬性信息描述
存取描述符(configurable,enumerable,get,set)
存儲描述符由一對getter-setter函數來描述屬性
描述符鄙視兩種形式之一,不能同時是兩者
### 2-2 Object.prototype
對象的原型對象屬性,
所有對象都是基于Object,通過指定Object.prototype為特定對象
可以實現對象對其他對象的屬性和方法繼承,也可以被覆蓋
### 2-3 Object.prototype.constructor
指向創建該對象原型的函數引用
屬性的值是一個函數本身。
### 2-4 Object.prototype.__proto__
對象的proto屬性和自己內部的Protototype指向相同的值
原型的值可以是一個對象也可以是Null。
使用Object.getPrototypeOf獲取對象的原型
## 3 對象方法
### 3-1 Object.create() 創建一個新的對象
~~~
;模擬實現
if(typeof Object.create != 'function'){
Object.create = (function(){
//為了節省內存,使用一個共享的構造器
function Temp() {};
// 使用 Object.prototype.hasOwnProperty 更安全的引用
var hasOwn = Object.prototype.hasOwnProperty;
return function (O) {
// 1. 如果 O 不是 Object 或 null,拋出一個 TypeError 異常。
if (typeof O != 'object') {
throw TypeError('Object prototype may only be an Object or null');
}
// 2. 使創建的一個新的對象為 obj ,就和通過
// new Object() 表達式創建一個新對象一樣,
// Object是標準內置的構造器名
// 3. 設置 obj 的內部屬性 [[Prototype]] 為 O。
Temp.prototype = O;
var obj = new Temp();
// 不要保持一個 O 的雜散引用(a stray reference)...
Temp.prototype = null;
// 4. 如果存在參數 Properties ,而不是 undefined ,
// 那么就把參數的自身屬性添加到 obj 上,就像調用
// 攜帶obj ,Properties兩個參數的標準內置函數
// Object.defineProperties() 一樣。
if (arguments.length > 1) {
// Object.defineProperties does ToObject on its first argument.
var Properties = Object(arguments[1]);
for (var prop in Properties) {
if (hasOwn.call(Properties, prop)) {
obj[prop] = Properties[prop];
}
}
}
// 5. 返回 obj
return obj;
};
})()
}
~~~
### 3-2 Object.is() 判斷兩個值是否同一個值
~~~
;基于===模擬實現
Object.is = function(x, y) {
// SameValue algorithm
if (x === y) { // Steps 1-5, 7-10
// Steps 6.b-6.e: +0 != -0
return x !== 0 || 1 / x === 1 / y;
} else {
// Step 6.a: NaN == NaN
return x !== x && y !== y;
}
};
~~~
### 3-3 Object.assign(target,...sources) 拷貝源對象到目標對象,返回目標對象
~~~
;模擬實現
if (!Object.assign) {
Object.defineProperty(Object, "assign", {
enumerable: false,
configurable: true,
writable: true,
value: function(target, firstSource) {
"use strict";
if (target === undefined || target === null)
throw new TypeError("Cannot convert first argument to object");
var to = Object(target);
for (var i = 1; i < arguments.length; i++) {
var nextSource = arguments[i];
if (nextSource === undefined || nextSource === null) continue;
var keysArray = Object.keys(Object(nextSource));
for (var nextIndex = 0, len = keysArray.length; nextIndex < len; nextIndex++) {
var nextKey = keysArray[nextIndex];
var desc = Object.getOwnPropertyDescriptor(nextSource, nextKey);
if (desc !== undefined && desc.enumerable) to[nextKey] = nextSource[nextKey];
}
}
return to;
}
});
}
~~~
~~~
;Demo 拷貝symbol類型的屬性
var o1 = { a: 1 };
var o2 = { [Symbol("foo")]: 2 };
var obj = Object.assign({}, o1, o2);
console.log(obj); // Object {a: 1, Symbol(foo): 2}
;繼承屬性和不可枚舉屬性是不能拷貝的
var obj = Object.create({foo: 1}, { // foo 是個繼承屬性。
bar: {
value: 2 // bar 是個不可枚舉屬性。
},
baz: {
value: 3,
enumerable: true
}
});
var copy = Object.assign({}, obj);
console.log(copy); // Object {baz: 3}
;原始值會被隱式轉換為其他包裝對象
var v1 = "123";
var v2 = true;
var v3 = 10;
var v4 = Symbol("foo")
var obj = Object.assign({}, v1, null, v2, undefined, v3, v4);
// 源對象如果是原始值,會被自動轉換成它們的包裝對象,
// 而 null 和 undefined 這兩種原始值會被完全忽略。
// 注意,只有字符串的包裝對象才有可能有自身可枚舉屬性。
console.log(obj); // { "0": "1", "1": "2", "2": "3" }
;拷貝過程中發生異常
var target = Object.defineProperty({}, "foo", {
value: 1,
writeable: false
}); // target 的 foo 屬性是個只讀屬性。
Object.assign(target, {bar: 2}, {foo2: 3, foo: 3, foo3: 3}, {baz: 4});
// TypeError: "foo" is read-only
// 注意這個異常是在拷貝第二個源對象的第二個屬性時發生的。
console.log(target.bar); // 2,說明第一個源對象拷貝成功了。
console.log(target.foo2); // 3,說明第二個源對象的第一個屬性也拷貝成功了。
console.log(target.foo); // 1,只讀屬性不能被覆蓋,所以第二個源對象的第二個屬性拷貝失敗了。
console.log(target.foo3); // undefined,異常之后 assign 方法就退出了,第三個屬性是不會被拷貝到的。
console.log(target.baz); // undefined,第三個源對象更是不會被拷貝到的。
~~~
### 3-4 Object.keys(obj) 返回對象的可枚舉自身屬性的屬性名組成的數組
### 3-5 Object.defineProperty(obj,prop,descriptor)
直接在對象上定義一個新屬性,并返回這個對象
### 3-6 Object.defineProperties(obj,props)
在一個對象上添加或修改一個或者多個自由屬性,并返回這個對象
### 3-7 Object.freeze(obj)
凍結一個對象。這個對象不可改變
### 3-8 Object.isFrozen(obj)
判斷一個對象是否被凍結
### 3-9 Object.preventExtensions(obj)
禁止一個對象可擴展,永遠不可能對對象添加新的屬性
### 3-10 Object.isExtensible(obj)
## 4 資源
[js中的object](https://segmentfault.com/a/1190000004224842)
- 概述
- 框架結構
- 編譯入口(\entries)
- web-compiler.js(web編譯)
- web-runtime.js(web運行時)
- web-runtime-wih-compiler.js(web編譯運行)
- web-server-renderer.js(web服務器渲染)
- 核心實現 (\core)
- index.js(核心入口)
- config.js(核心配置)
- core\util(核心工具)
- core\observer(雙向綁定)
- core\vdom(虛擬DOM)
- core\global-api(核心api)
- core\instance(核心實例)
- 模板編譯(\compiler)
- compiler\parser(模板解析)
- events.js(事件解析)
- helper.js(解析助手)
- directives\ref.js(ref指令)
- optimizer.js(解析優化)
- codegen.js(渲染生成)
- index.js(模板編譯入口)
- web渲染(\platforms\web)
- compiler(web編譯目錄)
- runtime(web運行時目錄)
- server(web服務器目錄)
- util(web工具目錄)
- 服務器渲染(\server)
- render-stream.js(流式渲染)
- render.js(服務器渲染函數)
- create-renderer.js(創建渲染接口)
- 框架流程
- Vue初始化
- Vue視圖數據綁定
- Vue數據變化刷新
- Vue視圖操作刷新
- 框架工具
- 基礎工具(\shared)
- 模板編譯助手
- 核心實例工具
- Web渲染工具
- 基礎原理
- dom
- string
- array
- function
- object
- es6
- 模塊(Module)
- 類(Class)
- 函數(箭頭)
- 字符串(擴展)
- 代理接口(Proxy)
- 數據綁定基礎
- 數據綁定實現
- mvvm簡單實現
- mvvm簡單使用
- vdom算法
- vdom實現
- vue源碼分析資料