声明
本文仅用于学习交流,切勿用作其他用途。
[TOC]
js 本来是没有对象的,不知道是不是因为单身久了,所以被迫有了对象。
对象创建
对象创建一般我们都是通过new function
来的,Es6中可以直接写class,这样子用法就是new一个class了。
当然也可以使用Object.create 和 Object.assign
对象的属性行为,这可是很有意义的
说到这个属性行为呀,我想起了基础数据类型的Symbol,以这个Symbol作为key值的对象,通过for...in 是拿不到这个Symbol的,不信大可以试试如下代码
var smb = Symbol("key1");
var a = {};
a[smb] = "hello wolrd";
console.log(Object.keys(a)) ;//看看这里是不是打印的[]就知道啦
//之前说过哦,要通过Object.getOwnPropertySymbols才能拿到哦
console.log(Object.getOwnPropertySymbols(a)) ;//[Symbol(key1)]
对于对象的属性行为,目前有 configurable,writable,enumerable,value
这个属性行为,其实说白了,和c++成员私有公有差不多的感觉,对于大家使用 Object.defineProperty的情况我不是很清楚,但是至少在我看到 '怎么在Es5中定义常量' 之前我是没怎么使用的,都是用已有的一些类呀什么直接拿过来用,或者直接把类当做hashMap来用...
定义常量
//浏览器下面可以用下述方法设置常量。
function setConst(name,value,log){
(log === undefined) && (log = true);
if(typeof name == 'string' && !name){
if( !window.hasOwnProperty(name)){
Object.defineProperty(window,name,{
configurable:false,//避免用defineProperty修改
writable:false,//不可写入
value:value
})
}else{
log && console.warn("const variable name",name,"already exists")
}
}else{
log && console.warn("name",name," is illegal")
}
}
//useage
setConst("Five",5);
console.log(Five);//5
setConst("Five",6);
console.log(Five);//5
Five = 7;
console.log(Five);//5
如上所示,js可以设置类的可写属性,枚举属性,是否可以修改对象属性的属性,以及值。
configurable
为false的时候,delete,defineProperty操作无效
writable
为false的时候 字面意思,不可更改,重新赋值无效
enumerable
为 false时,不出现在枚举列表,即Object.keys() 不能拿到对应的key
value
默认 undefined ,如字面意思,值
对象创建方式
- new function
- Object的操作,如Object.assign ,Object.create
- 直接以JSON的形式创建 --如 var a = { h:xxx }
- new class --等价于new function
new function
function T(){
}
var t = new T();//new function的时候返回的是一个类
var r = T();//这种情况就是执行一个function,没有new就是普通执行
//----------------------------------------------------
function F(){
(typeof this != 'undefined') && (this.t = "hello");
//如果这里没有返回或者返回不是对象,那么使用new的时候就返回this对象,
//如果这里返回了对象,那就不会返回this了
///////////////////////////////////////////////////
var t = {t:"test"};
return t;//这样写就是在玩火。不管怎么new,都是返回{t:"test"}这个对象,虽然引用不一样
///////////////////////////////////////////////////
}
var t = new F();//或者F()
console.log(t.t);//‘test’
//----------------------------------------------------
function G(){
if(new.target){ //我们可以这样检验调用的时候是否使用了new
//....
}
}
Object的操作
Object.creat方法创建一个新对象,使用现有的对象来提供新创建的对象的proto。 ;
Object.assign 方法用于将所有可枚举属性的值从一个或多个源对象复制到目标对象。它将返回目标对象。
//////////////////
var b = {k:1,k2:2};
var a = Object.create(b);//这里会创建对象a,把b作为a的原型,
console.log(a.k,a.k2,a.__proto__ == b)
b.k = 3,b.k2 = 4;
console.log(a.k,a.k2);// 3,4
var c = Object.create(a,{
key1:{
value: "this is a test case",
writable: true,
enumerable: false,
configurable: true
},
key2:{
value: "this is read-only value",
writable: false,
enumerable: true,
configurable: true
}
});//这里会把a作为c的原型,并且增加val属性,该属性的行为可以自行定义
console.log(c,c.key1 ) ;
console.log(c.k,c.k2);//3,4 这个就涉及到了原型链了
/////////////////////
var d = Object.assign(c,{k:6,k2:5},undefined,5,null,"hello",{});
console.log(d) ;// {k:6,k2:5,'0': 'h', '1': 'e', '2': 'l', '3': 'l', '4': 'o'}
//MDN上面说 原始类型会被包装,null 和 undefined 会被忽略。只有字符串的包装对象才可能有自身可枚举属性
//拷贝的是引用地址值来着。原型链中的和不可枚举的都不能拷贝。返回值是目标对象,也就是如下
console.log(c == d);//true
直接以JSON的形式创建
//////////////////
var a = {
key1:"1",
key2:2,
key3:false,
func4:function(){
return this.key1;
}
}
console.log(a.func4())
var b = JSON.parse('{ "t":1,"k":"hello","m":"world"} ')
console.log(b);//{ t: 1, k: 'hello', m: 'world' }
new class
//////////////////
class cls{
set key1(val){
this._key1 = val;
}
get key1(){
return this._key1;
}
constructor(){
this._key1 = "test";
}
}
var a = new cls();
//相当于
//function cls(){ this._key1 = "test" };
//var a = new cls();
//Object.defineProperty(a,"key1",{
//set:function(v){ this._key1 = v},get:function(){ return this._key1}
//})
原型链与继承
参照 https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Inheritance_and_the_prototype_chain
原型链
关于这个原型链我的理解有些不到位,欢迎大家指出我的错误的理解,
我的理解大概就是原型链就是对象的一个查找表,类似lua的原表,当我们试图 obj['key1'] 时,会先在obj下查找key1是否存在,没找到的情况再去 obj.__proto__
去查找,如果还没找到则去 obj.__proto__.__proto__
去查找,依次类推,直到找到或者遍历完原型链。
这个查找的概念就是在使用 obj['key'] 或者 obj.key 时执行的查找。
var a = { b :1,c:"2" }
var b = Object.create(a);//创建对象,指定对象的原型是a,
console.log(b);//{}
console.log(b.b,b.c);//这里在b里面没找到b和c属性,所以去原型链找
console.log(b.__proto__ == a);//true
所以我对原型链的理解为:对象所具有的默认值,修改原型链中的这个值(__proto__.xxx
)会影响具有相同原型链的其他对象,但是在自身增加对象则会覆盖这个值,如下
function T(){
}
T.prototype.test = 1;
var t1 = new T(),t2 = new T();;
console.log(t1.test,t2.test);//1,1
t1.__proto__.test = 2;
console.log(t1.test,t2.test);//2,2
t2.test = "hello";
console.log(t1.test,t2.test);//2,hello
继承
这个是个大问题,毕竟js不是面向对象的
,所以感觉原型链很大一部分感觉是为了继承而生的。
其操作大概就是 childCls.prototype = parent
我们用Object.create来创建对象的时候,实际上就是一个继承了。只是有时候可能没有那么明确,上面的原型链中的数据,也就是说继承之后的初始值,我们可以在继承之后去更改这些值。这个继承给人的感觉,很隐蔽。