JavaScript 对象所有API解析【2020版】

写于 2017年08月20日,虽然是2017年写的文章,但现在即将2020年依旧不过时,现在补充了2019年新增的ES10 Object.fromEntries()。发到公众号申明原创。若川顺便在此提前祝大家:2020年更上一层楼。

近日发现有挺多人对对象基础API不熟悉,举个开发中常见的需求,经常会有类似的封装http到原型Vue.prototype,一般人是这样封装的,但容易被篡改。

function Vue(){console.log('test vue');
}
function http(){console.log('我是调用接口的http');
}
Vue.prototype.$http = http;
var vm = new Vue();
vm.$http()
vm.$http = 1; // 一旦被修改,虽然一般正常情况下不会被修改
vm.$http(); // 再次调用报错

熟悉Object.defineProperty或者说熟悉对象API的人,一般是如下代码写的,则不会出现被修改的问题。

function Vue(){console.log('test vue');
};
function http(){console.log('我是调用接口的http');
};
Object.defineProperty(Vue.prototype, '$http', {get(){return http;}
});
var vm = new Vue();
vm.$http();
vm.$http = 1; // 这里无法修改
vm.$http(); // 调用正常

vue-router 源码里就是类似这样写的[1]this.$routerthis.$route无法修改。

// vue-router 源码
Object.defineProperty(Vue.prototype, '$router', {get () { return this._routerRoot._router }
})
Object.defineProperty(Vue.prototype, '$route', {get () { return this._routerRoot._route }
})

以下是正文,祝阅读愉快~

之前看到【深度长文】JavaScript 数组所有 API 全解密[2]和JavaScript 字符串所有 API 全解密[3]这两篇高质量的文章。发现没写对象 API 解析(估计是博主觉得简单,就没写)。刚好我看到《JavaScript 面向对象编程指南(第 2 版)》,觉得有必要写(或者说 chao)一下,也好熟悉下对象的所有 API 用法。

创建对象的两种方式:

var o = new Object();
var o = {}; // 推荐

该构造器可以接受任何类型的参数,并且会自动识别参数的类型,并选择更合适的构造器来完成相关操作。比如:

var o = new Object('something');
o.constructor; // ƒ String() { [native code] }
var n = new Object(123);
n.constructor; // ƒ Number() { [native code] }

一、Object 构造器的成员

Object.prototype

该属性是所有对象的原型(包括 Object对象本身),语言中的其他对象正是通过对该属性上添加东西来实现它们之间的继承关系的。所以要小心使用。比如:

var s = new String('若川');
Object.prototype.custom = 1;
console.log(s.custom); // 1

二、Object.prototype 的成员

Object.prototype.constructor

该属性指向用来构造该函数对象的构造器,在这里为Object()

Object.prototype.constructor === Object; // true
var o = new Object();
o.constructor === Object; // true

Object.prototype.toString(radix)

该方法返回的是一个用于描述目标对象的字符串。特别地,当目标是一个 Number 对象时,可以传递一个用于进制数的参数radix,该参数radix,该参数的默认值为 10。

var o = {prop:1};
o.toString(); // '[object Object]'
var n = new Number(255);
n.toString(); // '255'
n.toString(16); // 'ff'

Object.prototype.toLocaleString()

该方法的作用与toString()基本相同,只不过它做一些本地化处理。该方法会根据当前对象的不同而被重写,例如Date(),Number(),Array(),它们的值都会以本地化的形式输出。当然,对于包括Object()在内的其他大多数对象来说,该方法与toString()是基本相同的。在浏览器环境下,可以通过BOM对象Navigatorlanguage属性(在IE中则是userLanguage)来了解当前所使用的语言:

navigator.language; //'en-US'

Object.prototype.valueOf()

该方法返回的是用基本类型所表示的this值,如果它可以用基本类型表示的话。如果Number对象返回的是它的基本数值,而Date对象返回的是一个时间戳(timestamp)。如果无法用基本数据类型表示,该方法会返回this本身。

// Object
var o = {};
typeof o.valueOf(); // 'object'
o.valueOf() === o; // true
// Number
var n = new Number(101);
typeof n; // 'object'
typeof n.vauleOf; // 'function'
typeof n.valueOf(); // 'number'
n.valueOf() === n; // false
// Date
var d = new Date();
typeof d.valueOf(); // 'number'
d.valueOf(); // 1503146772355

Object.prototype.hasOwnProperty(prop)

该方法仅在目标属性为对象自身属性时返回true,而当该属性是从原型链中继承而来或根本不存在时,返回false

var o = {prop:1};
o.hasOwnProperty('prop'); // true
o.hasOwnProperty('toString'); // false
o.hasOwnProperty('formString'); // false

Object.prototype.isPrototypeOf(obj)

如果目标对象是当前对象的原型,该方法就会返回true,而且,当前对象所在原型上的所有对象都能通过该测试,并不局限与它的直系关系。

var s = new String('');
Object.prototype.isPrototypeOf(s); // true
String.prototype.isPrototypeOf(s); // true
Array.prototype.isPrototypeOf(s); // false

Object.prototype.propertyIsEnumerable(prop)

如果目标属性能在for in循环中被显示出来,该方法就返回true

var a = [1,2,3];
a.propertyIsEnumerable('length'); // false
a.propertyIsEnumerable(0); // true

三、在ES5中附加的Object属性

ES3中,除了一些内置属性(如:Math.PI),对象的所有的属性在任何时候都可以被修改、插入、删除。在ES5中,我们可以设置属性是否可以被改变或是被删除——在这之前,它是内置属性的特权。ES5中引入了属性描述符的概念,我们可以通过它对所定义的属性有更大的控制权。这些属性描述符(特性)包括:

value——当试图获取属性时所返回的值。writable——该属性是否可写。enumerable——该属性在for in循环中是否会被枚举configurable——该属性是否可被删除。set()——该属性的更新操作所调用的函数。get()——获取属性值时所调用的函数。另外,数据描述符(其中属性为:enumerableconfigurablevaluewritable)与存取描述符(其中属性为enumerableconfigurableset()get())之间是有互斥关系的。在定义了set()get()之后,描述符会认为存取操作已被 定义了,其中再定义valuewritable引起错误。以下是ES3风格的属性定义方式:

var person = {};
person.legs = 2;

以下是等价的 ES5 通过数据描述符定义属性的方式:

var person = {};
Object.defineProperty(person, 'legs', {value: 2,writable: true,configurable: true,enumerable: true
});

其中, 除了 value 的默认值为undefined以外,其他的默认值都为false。这就意味着,如果想要通过这一方式定义一个可写的属性,必须显示将它们设为true。或者,我们也可以通过ES5的存储描述符来定义:

var person = {};
Object.defineProperty(person, 'legs', {set:function(v) {return this.value = v;},get: function(v) {return this.value;},configurable: true,enumerable: true
});
person.legs = 2;

这样一来,多了许多可以用来描述属性的代码,如果想要防止别人篡改我们的属性,就必须要用到它们。此外,也不要忘了浏览器向后兼容ES3方面所做的考虑。例如,跟添加Array.prototype属性不一样,我们不能在旧版的浏览器中使用shim这一特性。另外,我们还可以(通过定义nonmalleable属性),在具体行为中运用这些描述符:

var person = {};
Object.defineProperty(person, 'heads', {value: 1});
person.heads = 0; // 0
person.heads; // 1  (改不了)
delete person.heads; // false
person.heads // 1 (删不掉)

Object.defineProperty(obj, prop, descriptor) (ES5)

具体用法可参见上文,或者查看 MDN。MDN Object.defineProperty(obj, descriptor)[4]

Vue.js 文档:**如何追踪变化**[5] 把一个普通 JavaScript 对象传给 Vue 实例的 data 选项,Vue 将遍历此对象所有的属性,并使用 Object.defineProperty 把这些属性全部转为 getter/setter。Object.defineProperty 是仅 ES5 支持,且无法 shim 的特性,这也就是为什么 Vue 不支持 IE8 以及更低版本浏览器的原因。

Object.defineProperties(obj, props) (ES5)

该方法的作用与defineProperty()基本相同,只不过它可以用来一次定义多个属性。比如:

var glass = Object.defineProperties({}, {'color': {value: 'transparent',writable: true},'fullness': {value: 'half',writable: false}
});
glass.fullness; // 'half'

Object.getPrototypeOf(obj) (ES5)

之前在ES3中,我们往往需要通过Object.prototype.isPrototypeOf()去猜测某个给定的对象的原型是什么,如今在ES5中,我们可以直接询问改对象“你的原型是什么?”

Object.getPrototypeOf([]) === Array.prototype; // true
Object.getPrototypeOf(Array.prototype) === Object.prototype; // true
Object.getPrototypeOf(Object.prototype) === null; // true

Object.create(obj, descr) (ES5)

该方法主要用于创建一个新对象,并为其设置原型,用(上述)属性描述符来定义对象的原型属性。

var parent = {hi: 'Hello'};
var o = Object.create(parent, {prop: {value: 1}
});
o.hi; // 'Hello'
// 获得它的原型
Object.getPrototypeOf(parent) === Object.prototype; // true 说明parent的原型是Object.prototype
Object.getPrototypeOf(o); // {hi: "Hello"} // 说明o的原型是{hi: "Hello"}
o.hasOwnProperty('hi'); // false 说明hi是原型上的
o.hasOwnProperty('prop'); // true 说明prop是原型上的自身上的属性。

现在,我们甚至可以用它来创建一个完全空白的对象,这样的事情在ES3中可是做不到的。

var o = Object.create(null);
typeof o.toString(); // 'undefined'

Object.getOwnPropertyDesciptor(obj, property) (ES5)

该方法可以让我们详细查看一个属性的定义。甚至可以通过它一窥那些内置的,之前不可见的隐藏属性。

Object.getOwnPropertyDescriptor(Object.prototype, 'toString');
// {writable: true, enumerable: false, configurable: true, value: ƒ toString()}

Object.getOwnPropertyNames(obj) (ES5)

该方法返回一个数组,其中包含了当前对象所有属性的名称(字符串),不论它们是否可枚举。当然,也可以用Object.keys()来单独返回可枚举的属性。

Object.getOwnPropertyNames(Object.prototype);
// ["__defineGetter__", "__defineSetter__", "hasOwnProperty", "__lookupGetter__", "__lookupSetter__", "propertyIsEnumerable", "toString", "valueOf", "__proto__", "constructor", "toLocaleString", "isPrototypeOf"]
Object.keys(Object.prototype);
// []
Object.getOwnPropertyNames(Object);
// ["length", "name", "arguments", "caller", "prototype", "assign", "getOwnPropertyDescriptor", "getOwnPropertyDescriptors", "getOwnPropertyNames", "getOwnPropertySymbols", "is", "preventExtensions", "seal", "create", "defineProperties", "defineProperty", "freeze", "getPrototypeOf", "setPrototypeOf", "isExtensible", "isFrozen", "isSealed", "keys", "entries", "values"]
Object.keys(Object);
// []

Object.preventExtensions(obj) (ES5)

Object.isExtensible(obj) (ES5)

preventExtensions()方法用于禁止向某一对象添加更多属性,而isExtensible()方法则用于检查某对象是否还可以被添加属性。

var deadline = {};
Object.isExtensible(deadline); // true
deadline.date = 'yesterday'; // 'yesterday'
Object.preventExtensions(deadline);
Object.isExtensible(deadline); // false
deadline.date = 'today';
deadline.date; // 'today'
// 尽管向某个不可扩展的对象中添加属性不算是一个错误操作,但它没有任何作用。
deadline.report = true;
deadline.report; // undefined

Object.seal(obj) (ES5)

Object.isSeal(obj) (ES5)

seal()方法可以让一个对象密封,并返回被密封后的对象。seal()方法的作用与preventExtensions()基本相同,但除此之外,它还会将现有属性 设置成不可配置。也就是说,在这种情况下,我们只能变更现有属性的值,但不能删除或(用defineProperty())重新配置这些属性,例如不能将一个可枚举的属性改成不可枚举。

var person = {legs:2};
// person === Object.seal(person); // true
Object.isSealed(person); // true
Object.getOwnPropertyDescriptor(person, 'legs');
// {value: 2, writable: true, enumerable: true, configurable: false}
delete person.legs; // false (不可删除,不可配置)
Object.defineProperty(person, 'legs',{value:2});
person.legs; // 2
person.legs = 1;
person.legs; // 1 (可写)
Object.defineProperty(person, "legs", { get: function() { return "legs"; } });
// 抛出TypeError异常

Object.freeze(obj) (ES5)

Object.isFrozen(obj) (ES5)

freeze()方法用于执行一切不受seal()方法限制的属性值变更。Object.freeze() 方法可以冻结一个对象,冻结指的是不能向这个对象添加新的属性,不能修改其已有属性的值,不能删除已有属性,以及不能修改该对象已有属性的可枚举性、可配置性、可写性。也就是说,这个对象永远是不可变的。该方法返回被冻结的对象。

var deadline = Object.freeze({date: 'yesterday'});
deadline.date = 'tomorrow';
deadline.excuse = 'lame';
deadline.date; // 'yesterday'
deadline.excuse; // undefined
Object.isSealed(deadline); // true;
Object.isFrozen(deadline); // true
Object.getOwnPropertyDescriptor(deadline, 'date');
// {value: "yesterday", writable: false, enumerable: true, configurable: false} (不可配置,不可写)
Object.keys(deadline); // ['date'] (可枚举)

Object.keys(obj) (ES5)

该方法是一种特殊的for-in循环。它只返回当前对象的属性(不像for-in),而且这些属性也必须是可枚举的(这点和Object.getOwnPropertyNames()不同,不论是否可以枚举)。返回值是一个字符串数组。

Object.prototype.customProto = 101;
Object.getOwnPropertyNames(Object.prototype);
// [..., "constructor", "toLocaleString", "isPrototypeOf", "customProto"]
Object.keys(Object.prototype); // ['customProto']
var o = {own: 202};
o.customProto; // 101
Object.keys(o); // ['own']

四、在ES6中附加的Object属性

Object.is(value1, value2) (ES6)

该方法用来比较两个值是否严格相等。它与严格比较运算符(===)的行为基本一致。不同之处只有两个:一是+0不等于-0,而是NaN等于自身。

Object.is('若川', '若川'); // true
Object.is({},{}); // false
Object.is(+0, -0); // false
+0 === -0; // true
Object.is(NaN, NaN); // true
NaN === NaN; // false

ES5可以通过以下代码部署Object.is

Object.defineProperty(Object, 'is', {value: function() {x, y} {if (x === y) {// 针对+0不等于-0的情况return x !== 0 || 1 / x === 1 / y;}// 针对 NaN的情况return x !== x && y !== y;},configurable: true,enumerable: false,writable: true
});

Object.assign(target, ...sources) (ES6)

该方法用来源对象(source)的所有可枚举的属性复制到目标对象(target)。它至少需要两个对象作为参数,第一个参数是目标对象target,后面的参数都是源对象(source)。只有一个参数不是对象,就会抛出TypeError错误。

var target = {a: 1};
var source1 = {b: 2};
var source2 = {c: 3};
obj = Object.assign(target, source1, source2);
target; // {a:1,b:2,c:3}
obj; // {a:1,b:2,c:3}
target === obj; // true
// 如果目标对象与源对象有同名属性,或多个源对象有同名属性,则后面的属性会覆盖前面的属性。
var source3 = {a:2,b:3,c:4};
Object.assign(target, source3);
target; // {a:2,b:3,c:4}

Object.assign只复制自身属性,不可枚举的属性(enumerablefalse)和继承的属性不会被复制。

Object.assign({b: 'c'},Object.defineProperty({}, 'invisible', {enumerable: false,value: 'hello'})
);
// {b: 'c'}

属性名为Symbol值的属性,也会被Object.assign()复制。

Object.assign({a: 'b'}, {[Symbol('c')]: 'd'});
// {a: 'b', Symbol(c): 'd'}

对于嵌套的对象,Object.assign()的处理方法是替换,而不是添加。

Object.assign({a: {b:'c',d:'e'}}, {a:{b:'hello'}});
// {a: {b:'hello'}}

对于数组,Object.assign()把数组视为属性名为 0、1、2 的对象。

Object.assign([1,2,3], [4,5]);
// [4,5,3]

Object.getOwnPropertySymbols(obj) (ES6)

该方法会返回一个数组,该数组包含了指定对象自身的(非继承的)所有 symbol 属性键。该方法和 Object.getOwnPropertyNames() 类似,但后者返回的结果只会包含字符串类型的属性键,也就是传统的属性名。

Object.getOwnPropertySymbols({a: 'b', [Symbol('c')]: 'd'});
// [Symbol(c)]

Object.setPrototypeOf(obj, prototype) (ES6)

该方法设置一个指定的对象的原型 ( 即, 内部[[Prototype]]属性)到另一个对象或 null__proto__属性用来读取或设置当前对象的prototype对象。目前,所有浏览器(包括IE11)都部署了这个属性。

// ES6写法
var obj = {method: function(){// code ...}
};
// obj.__proto__ = someOtherObj;
// ES5写法
var obj = Object.create(someOtherObj);
obj.method = function(){// code ...
};

该属性没有写入ES6的正文,而是写入了附录。__proto__前后的双下划线说明它本质上是一个内部属性,而不是正式对外的一个 API。无论从语义的角度,还是从兼容性的角度,都不要使用这个属性。而是使用Object.setPrototypeOf()(写操作),Object.getPrototypeOf()(读操作),或Object.create()(生成操作)代替。在实现上,__proto__调用的Object.prototype.__proto__Object.setPrototypeOf()方法的作用与__proto__作用相同,用于设置一个对象的prototype对象。它是ES6正式推荐的设置原型对象的方法。

五、在ES8中附加的Object属性

Object.getOwnPropertyDescriptors(obj) (ES8)

该方法基本与Object.getOwnPropertyDescriptor(obj, property)用法一致,只不过它可以用来获取一个对象的所有自身属性的描述符。

Object.getOwnPropertyDescriptor(Object.prototype, 'toString');
// {writable: true, enumerable: false, configurable: true, value: ƒ toString()}
Object.getOwnPropertyDescriptors(Object.prototype); // 可以自行在浏览器控制台查看效果。

Object.values(obj) (ES8)

Object.values() 方法与Object.keys类似。返回一个给定对象自己的所有可枚举属性值的数组,值的顺序与使用for...in循环的顺序相同 ( 区别在于for-in循环枚举原型链中的属性 )。

var obj = {a:1,b:2,c:3};
Object.keys(obj); // ['a','b','c']
Object.values(obj); // [1,2,3]

Object.entries(obj) (ES8)

Object.entries() 方法返回一个给定对象自己的可枚举属性[key,value]对的数组,数组中键值对的排列顺序和使用 for...in 循环遍历该对象时返回的顺序一致(区别在于一个for-in循环也枚举原型链中的属性)。

var obj = {a:1,b:2,c:3};
Object.keys(obj); // ['a','b','c']
Object.values(obj); // [1,2,3]
Object.entries(obj); // [['a',1],['b',2],['c',3]]

六、在ES10中附加的Object属性

Object.fromEntries(iterable) (ES10)

Object.fromEntries()方法返回一个给定可迭代对象(类似ArrayMap或其他可迭代对象)对应属性的新对象。

Object.fromEntries()Object.entries()的逆操作。

var arr = [['a',1],['b',2],['c',3]];
Object.fromEntries(obj); // {a: 1, b: 2, c: 3}
var entries = new Map([['name', '若川'],['age', 18]
]);
Object.fromEntries(entries) // {name: '若川', age: 18}

小结

细心的读者可能会发现MDN上还有一些API,本文没有列举到。因为那些是非标准的API。熟悉对象的 API 对理解原型和原型链相关知识会有一定帮助。常用的 API 主要有Object.prototype.toString()Object.prototype.hasOwnProperty()Object.getPrototypeOf(obj)Object.create()Object.definePropertyObject.keys(obj)Object.assign()

如果读者发现有不妥或可改善之处,再或者哪里没写明白的地方,欢迎评论指出。另外觉得写得不错,对您有些许帮助,可以点赞、评论、转发分享,也是对笔者的一种支持,非常感谢呀。

参考资料

MDN Object API[6]
JavaScript 面向对象编程指南(第 2 版)(豆瓣读书链接)[7]
阮一峰 ES6 标准入门 2[8]

原创精选文章

工作一年后,我有些感悟(写于2017年)

高考七年后、工作三年后的感悟

面试官问:JS的继承

前端使用puppeteer 爬虫生成《React.js 小书》PDF并合并

学习 jQuery 源码整体架构,打造属于自己的 js 类库

学习underscore源码整体架构,打造属于自己的函数式编程类库

学习 lodash 源码整体架构,打造属于自己的函数式编程类库

学习 sentry 源码整体架构,打造属于自己的前端异常监控SDK

学习 vuex 源码整体架构,打造属于自己的状态管理库

学习 axios 源码整体架构,打造属于自己的请求库

知乎问答:一年内的前端看不懂前端框架源码怎么办?

微信公众号

作者:常以若川为名混迹于江湖。前端路上 | PPT 爱好者 | 所知甚少,唯善学。
博客:https://lxchuan12.cn/posts/,阅读体验可能更好些。

若川视野

主要发布前端 | PPT | 生活 | 效率相关的文章,长按扫码关注。欢迎加我微信lxchuan12(注明来源,基本来者不拒),拉您进【前端视野交流群】,长期交流学习~

参考资料

[1]

vue-router 源码里就是类似这样写的: https://github.com/vuejs/vue-router/blob/dev/src/install.js#L38-L44

[2]

【深度长文】JavaScript数组所有API全解密: http://louiszhai.github.io/2017/04/28/array/

[3]

JavaScript字符串所有API全解密: http://louiszhai.github.io/2016/01/12/js.String/

[4]

MDN Object.defineProperty(obj, descriptor): https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty

[5]

如何追踪变化: https://cn.vuejs.org/v2/guide/reactivity.html

[6]

MDN Object API: https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object

[7]

JavaScript面向对象编程指南(第2版)(豆瓣读书链接): https://book.douban.com/subject/26302623/

[8]

阮一峰 ES6标准入门2: http://es6.ruanyifeng.com/

由于公众号限制外链,点击读原文,或许阅读体验更佳,觉得文章不错,可以点个在看呀^_^

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/276491.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

PHP生成各种验证码和Ajax验证

转载链接:http://www.helloweba.com/view-blog-191.html 验证码在WEB应用中非常重要,通常用来防止用户恶意提交表单,如恶意注册和登录、论坛恶意灌水等。本文将通过实例讲解使用PHP生成各种常见的验证码包括数字验证码、数字字母验证码、中文…

若川的2019年度总结,波澜不惊

从2014年开始写年度总结至今已经六个年头了。正如孔子所说:逝者如斯夫,不舍昼夜。2019年的年度总结写得比较晚,都快农历新年了,此刻在家里继续写完这篇文章。往年基本是元旦之后几天就写完了。我的年度总结尽量写得非技术人员也能…

如何正确选择仓储物流供应商?

如何正确选择仓储物流供应商? 以前有做电商的朋友向我咨询过怎么去选择优质的仓储物流供应商?有哪些能做作为关键问题进行参考。作为一个优秀的合作伙伴是可以为客户提供超乎预期的服务的,上海维佳供应链服务专业提供物流外包解决仓储物流供应…

Realtime Ray Tracing RenderMan Point Cloud

这里演示的是演示的是光线与包围盒测试。在装备Winfast 8800GT 512M的台式机上可以进行每秒4.6亿次点到射线的距离计算计算,用于判断点是否真正的与射线相交。外部数据的填充与准备延迟依旧是GPGPU应用的一个巨大门槛。白色是命中的包围盒,绿色的就是射线…

如何制定有价值的目标

写于2017年07月09日23:29现在修改发布到公众号声明原创公司会制定一系列目标,个人也可以制定一些目标,有利于自我学习成长。那么看我这篇文章可以告诉你如何制定有价值的目标。会制定有价值的目标,绝对超越很多人。SMART原则王健林之前说定个…

清除dns缓存命令行_怎么防止移动dns劫持,防止移动dns劫持要先了解什么是dns劫持...

本人以网络技术出身,近两年接触CDN网络,处理了一些CDN方面的网络问题,大多数以运营商丢包,延迟抖动为主,也处理一些硬件故障,比如机械硬盘的读写io测试,内存条兼容性测试,服务器IPMI…

移动硬盘格式化(pc和mac共用)-菜鸟级解决方案[转]

用pc的时候买了一个320G的移动硬盘,从来没考虑过什么格式化的问题,插上就用了。 后来接触mac才发现pc和mac在移动存储设备的格式化上还是有不少冲突的。如果你的移动硬盘mac上不能修改,或者pc上找不到,那就尽情得批判万恶的资本主…

回答知乎问题:你写过什么自认为惊艳的诗?

首次整理于 2019-07-27 22:04:00,现在整理发布在公众号申明原创。整理了一下大学期间2012年~2016年发布在QQ空间,自己感觉写得还行的七首“诗词”。回答知乎问题:你写过什么自认为惊艳的诗?中国古诗词博大精深。小时候…

密码可逆不可逆选择_膝关节损伤不可逆!跑步要注意!

膝盖同时也是运动者最常受伤的关节。根据美国运动医学整型外科协会的报告,美国每年约有三百万人拉伤、挫伤、或扭伤他们的膝部,其中约有一半是因为运动引起的。而对于跑者而言,影响最大的就是我们的膝关节。换言之,长跑的潜在危害…

面试官问:能否模拟实现JS的call和apply方法

写于2018年11月30日,发布在掘金上阅读量近一万,现在发布到微信公众号申明原创。相对比较基础的知识,虽然日常开发可能用得比较少,各种源码中有很多call和apply,需要掌握。前言这是面试官问系列的第三篇,旨在…

prometheus 发送恢复 值_Prometheus基础知识介绍

【编者的话】本文会让你了解Prometheus是什么,并让你理解它在监控领域的适用场景。Prometheus起源很久以前,加利福尼亚州山景城有一家名为Google的公司。他们推出了大量产品,其中最著名的是广告系统和搜索引擎平台。为了运行这些不同的产品&a…

面试官问:JS的this指向

写于2018年12月25日,发布在掘金上阅读量近一万,现在发布到微信公众号申明原创。前言这是面试官问系列的第四篇,旨在帮助读者提升JS基础知识,包含new、call、apply、this、继承相关知识。面试官问系列文章如下:感兴趣的…

要做PPT,一直找不到资源?

写于 2016年6月,工作后就很少做PPT了。但工作至今也有人问我如何做PPT有没有模板之类的问题(比如:大学室友做公司年度汇报时也找到我问有没有模板,我发了这篇文章给他,他说不记得我写了这篇文章呀)&#xf…

Linux系统安装Appach 2.4.6

转载链接:http://www.cnblogs.com/kerrycode/p/3261101.html Apache简介 Apache HTTP Server(简称Apache)是Apache软件基金会的一个开放源码的网页服务器,可以在大多数计算机操作系统中运行,由于其多平台和安全性被广…

学习 redux 源码整体架构,深入理解 redux 及其中间件原理

如果觉得内容不错,可以设为星标置顶我的公众号1. 前言你好,我是若川。这是学习源码整体架构系列第八篇。整体架构这词语好像有点大,姑且就算是源码整体结构吧,主要就是学习是代码整体结构,不深究其他不是主线的具体函数…

pdf安装包_有么有pdf控件,不需要用户安装任何安装包直接打印的?

如果开发一个软件,需要用到PDF功能,您的选择是基于Adobe PDF吗? 如果是基于Adobe PDF,需要用户安装一个几十M的Adobe的安装包,这显然是不友好的。即使目前也有了一些其它的阅读器,大小也还好。但是&#xf…

[转] C#异步操作

Title 通过委托实现异步调用中BeginInvoke及回调函数的使用 通过委托实现异步调用的步骤: 1.定义委托。 2.将要进行异步调用的方法“实例化”到定义的委托。 3.在委托上调用BeginInvoke方法。其中,BeginInvoke的参数由三个部分构成。第一部分&#xff1…

HTTP Server Error 500 内部服务器错误

问题:HTTP500错误 或 Server Application Error ------------------------------------Server Application ErrorThe server has encountered an error while loading an application during the processing of your request. Please refer to the event log for mo…

使用 ohmyzsh 打造 windows、ubuntu、mac 系统高效终端命令行工具

如果觉得内容不错,可以设为星标置顶我的公众号原标题名:oh my zsh 和 windows git bash 设置别名提高效率写于2018年06月03日在我的微信交流群中听闻很多前端开发比较贫穷,没有买mac电脑(比如我),也没有用过…

request获取mac地址_【Go】获取用户真实的ip地址

原文链接:https://blog.thinkeridea.com/201903/go/get_client_ip.html用户请求到达提供服务的服务器中间有很多的环节,导致服务获取用户真实的 ip 非常困难,大多数的框架及工具库都会封装各种获取用户真实 ip 的方法,在 exnet 包…