JavaScript Object


本文應該不會提到

  • OOP
  • class

本文會提到


摘要

名詞:

  1. 屬性 properties, 屬性 attributes , 方法, 函式
  2. 物件導向, 類別, 原型

正文

物件

物件實字 object literal
{ }

建構式
function() {}

// Object initialiser or literal
{ [ nameValuePair1[, nameValuePair2[, ...nameValuePairN] ] ] }

// Called as a constructor
new Object([value])

建立物件

Object.create()

Object.create()
指定其原型物件與屬性,創建一個新物件。
語法 Object.create(proto[, propertiesObject])

var o;

// 建立以null為原型的物件
o = Object.create(null);


o = {};
// 等同於:
o = Object.create(Object.prototype);

範例

function heroCreator (name, act) {
const hero = {} //物件實字宣告方法
hero.name = name
hero.act = act
hero.attack = function () { console..log( ${this.name} 使用 ${this.act} 攻擊 ) }
return h
}

const pika = heroCreator('皮卡丘', '十萬伏特')
pika.attack()

現在想要改成共用方法 attack,不要直接寫進 creator

function heroCreator (name, act) {
const hero = {} //物件實字宣告方法
hero.name = name
hero.act = act
// hero.attack = function () { console..log( ${this.name} 使用 ${this.act} 攻擊 ) }
// 抽出來
return h
}

function attack (act) {
console..log( ${this.name} 使用 ${this.act} 攻擊
}

const pika = heroCreator('皮卡丘', '十萬伏特')
pika.attack = attack
pika.attack()


const actions = {
atk: function () { console..log(${this.name} 使用攻擊) } def: function () { console..log(${this.name} 防禦) }
}

function heroCreator(name) {
//const h = {}
const h = Object.create(actions)
h.name = name
h.act = act // act not defined
retrun h
}

用繼承的方式而不是直接寫進 creator,避免我忘記傳進 act


proto 所有的物件都有這個屬性
當在這個物件裡找不到某個屬性時,會去找物件的 proto 去尋找原型,一直到 null

const h1 = heroCreator('pika')
console.log(h1.proto) // 原型是 actions


JS 的標準內建物件

  • Object
  • Function
  • Boolean
  • Number
  • String
  • Array
  • ...
  • 所有的 Function 都有 prototype
  • JS 有純值
    1.__proto__
    Uncaught SyntaxError: Invalid or unexpected token
    
let a = 1
a.__proto__
Number {0, constructor: ƒ, toExponential: ƒ, toFixed: ƒ, toPrecision: ƒ, …}
//自動 boxing 成 Number

.create vs .proto 指向

heroObj.create(actions)

等於

heroObj.__proto__ = actions

// 不要這樣做


this

誰呼叫,誰實 this

fun a () {
    fun b() {}

    b() //caller is global, this is window, 跟執行堆疊無關
}

fun heroFactory(name,act) {
this.name = name //this = global
}

fun heroFactory(name,act) {
    var a = b = 2 // b=2 會被提升到 global 宣告一個 var b;
    log(a) //2
    lob(b) //2
}

log(a) //not defined
lob(b) //2  b 已經被拉到全域宣告

new 做了什麼?

改變 this 的指向

const h3 = new heroFactory('h3','run') // new 會幫忙做兩件事 1. this 指向 action 2. retrun this
const h4 = heroFactory('h4','fly') // retrun undefined

new hF() 裡
retrun 原始型別會被無視, return 複雜型別才可以

new
創出一個新的 object,我們叫它 O
把 O 的 proto 指向 "原型" 的 prototype,才能繼承原型鍊
拿 O 當作 context,呼叫 Person 這個建構函式
回傳 O


function 是物件

func a() {
log(this.age) //this == global this.name == undefined
}

a.age = 18


proto vs prototype

proto 是指向原型的 prototype 的一個屬性

fn.prototype 預設是空物件

物件原型
可以用不同方式 建構式 物件實字 定義
instance 的 proto 會指向他的原型,自定義的物件的 proto 會指向 function

Person.prototype:
instance 的屬性,所有的物件實例都會有這個屬性

proto 指向 prototype

============================

參考

Javascripter 必須知道的繼承 prototype, [[prototype]], proto
JS基本觀念: 原型鏈(prototype chain)
該來理解 JavaScript 的原型鍊了
你懂 JavaScript 嗎?#19 原型(Prototype)
js中proto和prototype的区别和关系?

MDN JavaScript 教學

延伸

https://developer.mozilla.org/zh-TW/docs/Web/JavaScript
[[Prototype]] javascript proto
javascript interview question "this"
jQuery source code
IFEE
contentful

not definded & undefined

hello()
Uncaught ReferenceError: hello is not defined

ReferenceError 沒有宣告過

let b = {} // 創造一個物件 b (用物件實字 or 建構式)
b.hello()
Uncaught TypeError: Cannot read property 'hello' is not a function

注意: 不是印出 undefuned ,而是 TypeError is not a function
如果改成 b.hello 就是 undefuned

undefined 怎麼出來的 => 原型鍊上找不到
b.protop 順著鍊上找到最後是 null,所以回傳 undefined

new

  1. 改變 this 的指向

hero = new Hero()

prototype vs proto

RECAP

fn.prototype 建構
fn.proto 指向原型

#javascript







Related Posts

串接 API -- block-scoped 問題

串接 API -- block-scoped 問題

【Day04】Bootstrap介紹 + 套版

【Day04】Bootstrap介紹 + 套版

[ week 6 ] CSS 筆記+作業

[ week 6 ] CSS 筆記+作業




Sponsored



Comments