/**
* 字符串字面量可以访问属性或方法,是因为引擎自动把字面量转换为String对象
*/
var strPrimitive = 'I am a string';
console.log(typeof strPrimitive); // string
console.log(strPrimitive instanceof String); // false
var strObject = new String('I am a string');
console.log(typeof strObject); // object
console.log(strObject instanceof String); // true
/**
* 浅拷贝
* Object.assign(..)
*/
function fn () {}
var myObject = {
name: 'yt',
age: 27,
fn: fn
};
var newObj = Object.assign({}, myObject);
console.log(newObj.name) // yt
console.log(newObj.fn === fn) // true
/**
* 对象常量
*/
var myObj = {};
Object.defineProperty(myObj, 'FAVORITE_NUMBER', {
value: 27,
writable: false,
configurable: false,
})
console.log(myObj.FAVORITE_NUMBER) // 27
myObj.FAVORITE_NUMBER = 72
console.log(myObj.FAVORITE_NUMBER) // 72
/**
* 禁止扩展
*/
var myObject2 = {
a: 28
};
Object.preventExtensions(myObject2);
myObject2.b = 30;
console.log(myObject2.b) // undefined
/**
* getter
*/
var testObj = {
// 给 a 定义一个 getter
get a() {
return 2;
}
};
Object.defineProperty(testObj, 'b', {
get: function() {
return this.a * 2;
},
enumerable: true
});
console.log(testObj.a); // 2
console.log(testObj.b); // 4
testObj.a = 3 // 只定义了 getter,set操作会忽略赋值操作
console.log(testObj.a) // 2
/**
* setter getter 一般一起出现
*/
var testObj2 = {
// 给 a 设置一个 getter
get a() {
return this._a_;
},
// 给 a 设置一个 setter
set a(val) {
this._a_ = val * 2;
}
}
testObj2.a = 2;
console.log(testObj2.a) // 4
testObj2.a = 3;
console.log(testObj2.a) // 6
/**
* 存在性
*/
var testObj3 = {
a: 2
};
console.log('a' in testObj3) // true
console.log('b' in testObj3) // false
console.log(testObj3.hasOwnProperty('a')) // true
console.log(testObj3.hasOwnProperty('b')) // false
/**
* 枚举
*/
var testObj4 = { };
Object.defineProperty(testObj4, 'a', {
enumerable: true,
value: 2
});
Object.defineProperty(testObj4, 'b', {
enumerable: false, // 不可枚举
value: 3
});
console.log(testObj4.b) // 3
console.log(testObj4.hasOwnProperty('b')) // true
for (var k in testObj4) {
console.log(k, testObj4[k])
}
// 'a' 2
// 检查给定得属性名是否直接存在于该对象中
console.log(testObj4.propertyIsEnumerable('a')) // true
console.log(testObj4.propertyIsEnumerable('b')) // false
// Object.keys() 返回一个数组,包含所有可枚举属性
console.log(Object.keys(testObj4)) // [ 'a' ]
// Object.getOwnPropertyNames() 返回一个数组,包含所有属性,不管是否可枚举
console.log(Object.getOwnPropertyNames(testObj4)) // [ 'a', 'b' ]
/**
* 遍历
*/
var myArray = [1, 2, 3];
for(var i = 0; i < myArray.length; i++) {
console.log(myArray[i]);
}
// 1 2 3
/**
* arr.forEach(callback(currentValue[, index[, arrary]])[, thisArg]);
*/
function logArrayElements(element, index, array) {
console.log('a[' + index + '] = ' + element);
}
// 注意索引 2 被跳过了,因为在数组的这个位置没有项
[2, 5, , 9].forEach(logArrayElements);
// a[0] = 2
// a[1] = 5
// a[3] = 9
// 对象复制函数
function copy(obj) {
// Object.create()方法创建一个新对象,使用现有的对象来提供新创建的对象的__proto__
// Object.getPrototypeOf(object)方法返回指定对象的原型(内部[[Prototype]]属性的值
var copy = Object.create(Object.getPrototypeOf(obj));
// Object.getOwnPropertyNames(obj)方法返回一个由指定对象的所有自身属性的属性名(包括不可枚举属性但不包括Symbol值作为名称的属性)组成的数组
var propNames = Object.getOwnPropertyNames(obj);
propNames.forEach(function(name) {
// Object.getOwnPropertyDescriptor(obj, prop)方法返回指定对象上一个自有属性对应的属性描述符。
// (自有属性指的是直接赋予该对象的属性,不需要从原型链上进行查找的属性)
var desc = Object.getOwnPropertyDescriptor(obj, name);
// Object.defineProperty(obj, prop, descriptor)方法会直接在一个对象上定义一个新属性,
// 或者修改一个对象的现有属性, 并返回这个对象
Object.defineProperty(copy, name, desc);
});
return copy;
}
var copyObj1 = {
a: 1,
b: 2
};
var copyObj2 = copy(copyObj1);
console.log(copyObj2) // { a: 1, b: 2 }
console.log(copyObj2 === copyObj1) // false
/**
* arr.some(callback(element[, index[, array]])[, thisArg])
* 方法测试数组中是不是有元素通过了被提供的函数测试
* 它返回一个布尔值
*/
var event1 = function(item, index) {
return item === index
};
var event2 = function(item) {
return item % 2 === 0
};
var arrTest = [1, 2, 3, 4];
console.log(arrTest.some(event1)) // false
console.log(arrTest.some(event2)) // true
/**
* arr.every(callback(element[, index[, array]])[, thisArg])
* 方法测试一个数组内的所有元素是否都能通过某个指定函数的测试
* 它返回一个布尔值
*/
var testEveryArr1 = [1, 2, 3];
var testEveryArr2 = [10, 20, 30];
console.log(testEveryArr1.every(item => item >= 10)) // false
console.log(testEveryArr2.every(item => item >= 10)) // true
/**
* for...of
* 在可迭代对象(包括 Array,Map,Set,String,TypedArray,arguments 对象等等)上创建一个迭代循环
* 调用自定义迭代钩子,并为每个不同属性的值执行语句
*
* for (variable of iterable) {
* statements
* }
* variable - 在每次迭代中,将不同属性的值分配给变量
* iterable - 被迭代枚举其属性的对象
*
* for...in 语句以任意顺序迭代对象的可枚举属性
* for...of 语句遍历可迭代对象定义要迭代的数据
*/
var testForOfArr = [10, 20, 30];
for(var v of testForOfArr) {
console.log(v)
}
// 10 20 30
for(var key in testForOfArr) {
console.log(key)
}
// 0 1 2
/**
* 数组内置的 '@@iterator'
* Symbol.iterator获取对象的 '@@iterator' 内部属性
*/
var it = testForOfArr[Symbol.iterator]();
console.log(it) // Object [Array Iterator] {}
console.log(it.next()) // { value: 10, done: false }
console.log(it.next()) // { value: 20, done: false }
console.log(it.next()) // { value: 30, done: false }
console.log(it.next()) // { value: undefined, done: true }
/**
* 自定义对象的 '@@iterator'
* 普通对象没有内置的 '@@iterator',所以无法自动完成 for...of 遍历
*/
var testIteratorObj = {
a: 2,
b: 3
};
Object.defineProperty(testIteratorObj, Symbol.iterator, {
enumerable: false,
writable: false,
configurable: true,
value: function() {
var o = this;
var idx = 0;
var ks = Object.keys(o);
return {
next: function() {
return {
value: o[ks[idx++]], // ks = ['a'], idx = 0; ks[0] = 'a'; o[ks[0]] = o.a = 2;
done: idx > ks.length
}
}
}
}
});
for(var value of testIteratorObj) {
console.log({value})
}
// { value: 2 }
// { value: 3 }
var itObj = testIteratorObj[Symbol.iterator]();
console.log(itObj.next()) // { value: 2, done: false }
console.log(itObj.next()) // { value: 3, done: false }
console.log(itObj.next()) // { value: undefined, done: true }
/**
* 迭代其他可迭代对象
*/
var randomObj = {
[Symbol.iterator]() {
return {
next: function() {
return {
value: Math.random()
};
}
};
}
};
var randomsPool = [];
for(var n of randomObj) {
randomsPool.push(n);
if(randomsPool.length === 100) break;
}
/**
* 用 Object.create实现类式继承
* Object.create()方法创建一个新对象,使用现有的对象来提供新创建的对象的__proto__
*/
// Shape - 父类(superclass)
function Shape() {
this.x = 0;
this.y = 0;
}
// 父类的方法
Shape.prototype.move = function(x, y) {
this.x += x;
this.y += y;
console.info('Shape moved.');
}
// Rectangle - 子类(subclass)
function Rectangle() {
Shape.call(this)
}
function OtherClass() {}
OtherClass.prototype.otherMethod = function() {
console.log('OtherClass.')
}
// 子类续承父类
Rectangle.prototype = Object.create(Shape.prototype);
// 混合其他
Object.assign(Rectangle.prototype, OtherClass.prototype);
Rectangle.prototype.constructor = Rectangle;
var rect = new Rectangle();
console.log('Is rect an instance of Rectangle?', rect instanceof Rectangle); // true
console.log('Is rect an instance of Shape?', rect instanceof Shape); // true
rect.move(1, 1); // Shape moved.
rect.otherMethod(); // OtherClass.
/**
* 使用 Object.create 的 propertyObject 参数
*/
var o;
o = Object.create(null); // 创建一个原型为null的空对象
o = {};
// 以字面量方式创建的空对象就相当于:
o = Object.create(Object.prototype);
o = Object.create(Object.prototype, {
// foo会成为所创建对象的数据属性
foo: {
writable: true,
configurable: true,
value: 'hello'
},
// bar会成为所创建对象的访问器属性
bar: {
configurable: false,
get: function() {
return 10
},
set: function(value) {
console.log("Setting `o.bar` to", value);
}
}
});
console.log(o.foo) // hello
console.log(o.bar) // 10
o.bar = 1;
console.log(o.bar) // 10
function Constructor() { }
var o2 = new Constructor();
console.log({o2}) // { o2: Constructor {} }
// 相当于:
var o3 = Object.create(Constructor.prototype)
console.log({o3}) // { o3: Constructor {} }
// 创建一个以另一个空对象为原型,且拥有一个属性p的对象
var o4 = Object.create({}, {
p: {
value: 12
}
});
console.log({o4}) // { o4: {} }
console.log(o4.p) // 12
// 省略了的属性特性默认为false,所以属性p是不可写,不可枚举,不可配置的:
o4.p = 21;
console.log(o4.p) // 12
o4.q = 12
for (var prop in o4) {
console.log(prop)
}
//"q"
delete o4.p
console.log(o4.p) // 12
// 创建一个可写 可枚举 可配置的属性 p
var o5 = Object.create({}, {
p: {
value: 15,
writable: true,
enumerable: true,
configurable: true
}
});
o5.p = 51;
console.log(o5.p) // 51
o5.q = 12
for (var prop in o5) {
console.log({prop})
}
// { prop: 'p' }
// { prop: 'q' }
delete o5.p
console.log(o5.p) // undefined
/**
* Object.getPrototypeOf(object)
* 返回指定对象的原型
*/
var prototype1 = {};
var o6 = Object.create(prototype1);
console.log(Object.getPrototypeOf(o6) === prototype1) // true
Object.getPrototypeOf( {} ) === Object.prototype; // true
/**
* Object.getOwnPropertyNames(obj)
* 返回一个由指定对象的所有自身属性的属性名(包括不可枚举属性但不包括Symbol值作为名称的属性)组成的数组
*/
var arr7 = ['a', 'b', 'c'];
var o7 = {
0: 'a',
1: 'b',
2: 'c'
}
console.log(Object.getOwnPropertyNames(arr7)) // [ '0', '1', '2', 'length' ]
console.log(Object.getOwnPropertyNames(o7)) // [ '0', '1', '2' ]
/**
* Object.getOwnPropertyDescriptor(obj, prop)
* 返回指定对象上一个自有属性对应的属性描述符。
* 自有属性指的是直接赋予该对象的属性,不需要从原型链上进行查找的属性
*/
var o8 = {
bar: 2,
get foo() { return 17; },
baz: 10
};
console.log(Object.getOwnPropertyDescriptor(o8, 'bar'));
// { value: 2, writable: true, enumerable: true, configurable: true }
console.log(Object.getOwnPropertyDescriptor(o8, 'foo'));
// { get: [Function: get foo],
// set: undefined,
// enumerable: true,
// configurable: true }
/**
* Object.defineProperty(obj, prop, descriptor)
* 会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性, 并返回这个对象
*/
Object.defineProperty(o8, 'baz', {
value: 8675309,
writable: false,
enumerable: false
});
console.log(Object.getOwnPropertyDescriptor(o8, 'baz'));
// { value: 8675309,
// writable: false,
// enumerable: false,
// configurable: true }
/**
* Object.keys(obj)
* 会返回一个由一个给定对象的自身可枚举属性组成的数组
* 数组中属性名的排列顺序和使用 for...in 循环遍历该对象时返回的顺序一致
* 如果对象的键-值都不可枚举,那么将返回由键组成的数组
*/
var arr8 = ['a', 'b', 'c'];
console.log(Object.keys(arr8)); // [ '0', '1', '2' ]
var anObj = { 100: 'a', 2: 'b', 7: 'c' };
console.log(Object.keys(anObj)); // ['2', '7', '100']