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.pswp.cn/news/276491.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/276491.shtml
英文地址,請注明出處:http://en.pswp.cn/news/276491.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

javascript操作符之new 也瘋狂 (2)

JavaScript本是一種基于原形的(prototypal)語言,但它的“new”操作符看起來有點像經典語言。這迷惑了廣大程序員們,并導致了很多使用上的問題。 在JavaScript中,不要用到new Object()這種操作,該用{ }來代替…

python中if語句缺省else_9_【Python學習分享文章】_if(條件語句)

【Python學習分享文章】_if(條件語句)_logicalJudgement介紹及基本操作綜述計算機的“條件語句”和生活中的“條件成立”是不一樣的。一個生活中的例子如果被計算機執行則是如下段子:老婆讓程序員老公去買蘋果,說:“去水果店買5個蘋果&#x…

PHP生成各種驗證碼和Ajax驗證

轉載鏈接:http://www.helloweba.com/view-blog-191.html 驗證碼在WEB應用中非常重要,通常用來防止用戶惡意提交表單,如惡意注冊和登錄、論壇惡意灌水等。本文將通過實例講解使用PHP生成各種常見的驗證碼包括數字驗證碼、數字字母驗證碼、中文…

若川的2019年度總結,波瀾不驚

從2014年開始寫年度總結至今已經六個年頭了。正如孔子所說:逝者如斯夫,不舍晝夜。2019年的年度總結寫得比較晚,都快農歷新年了,此刻在家里繼續寫完這篇文章。往年基本是元旦之后幾天就寫完了。我的年度總結盡量寫得非技術人員也能…

如何正確選擇倉儲物流供應商?

如何正確選擇倉儲物流供應商? 以前有做電商的朋友向我咨詢過怎么去選擇優質的倉儲物流供應商?有哪些能做作為關鍵問題進行參考。作為一個優秀的合作伙伴是可以為客戶提供超乎預期的服務的,上海維佳供應鏈服務專業提供物流外包解決倉儲物流供應…

在虛機上安裝WIN2003

Moss2-turn on-WM;SJY;SJYM;666666備注:計算機名在網絡上必須是唯一的。姓名:WP; 單位:SJY; 計算機名稱:SJYP; 密碼:666666server 2003 R2版 MDGJK-PF6YQ-PD8DJ-RFQVM-7WKWG在“網絡設置”頁面上,單擊“典型…

python字典獲取關聯值_【Python實戰12】使用字典關聯數據

現在我的手里有了新的一組數據,數據內容如下:james.txt:James Lee,2002-3-14,2-34,3:21,2.34,2.45,3.01,2:01,2:01,3:10,2-22,2-01,2.01,2:16julie.txt:Julie Jones,2002-8-17,2.59,2.11,2:11,2:23,3-10,2-23,3:10,3.21,3-21,3.01…

Sending HTML content in an email using PHP

轉載鏈接&#xff1a;http://code.web-max.ca/misc_htmlemail.php 發送一個HTML格式的電子郵件&#xff0c;主要在郵件的頭信息中定義郵件正文的類型&#xff1a; Content-Type:text/html;charset"utf-8"。 示例&#xff1a; <?php// Example $HTML …

Realtime Ray Tracing RenderMan Point Cloud

這里演示的是演示的是光線與包圍盒測試。在裝備Winfast 8800GT 512M的臺式機上可以進行每秒4.6億次點到射線的距離計算計算&#xff0c;用于判斷點是否真正的與射線相交。外部數據的填充與準備延遲依舊是GPGPU應用的一個巨大門檻。白色是命中的包圍盒&#xff0c;綠色的就是射線…

SharePoint文檔上傳管理

前臺代碼: <% Control Language"C#" AutoEventWireup"true" CodeBehind"FileUpload.ascx.cs" Inherits"UploadFile.FileUpload" %><table><tr><td style"width:138px; height: 24px;">請選擇列表:…

如何制定有價值的目標

寫于2017年07月09日23:29現在修改發布到公眾號聲明原創公司會制定一系列目標&#xff0c;個人也可以制定一些目標&#xff0c;有利于自我學習成長。那么看我這篇文章可以告訴你如何制定有價值的目標。會制定有價值的目標&#xff0c;絕對超越很多人。SMART原則王健林之前說定個…

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

本人以網絡技術出身&#xff0c;近兩年接觸CDN網絡&#xff0c;處理了一些CDN方面的網絡問題&#xff0c;大多數以運營商丟包&#xff0c;延遲抖動為主&#xff0c;也處理一些硬件故障&#xff0c;比如機械硬盤的讀寫io測試&#xff0c;內存條兼容性測試&#xff0c;服務器IPMI…

php 修改上傳文件大小 (max_execution_time post_max_size)

轉載鏈接&#xff1a;http://hi.baidu.com/ttl289/item/683c8223a54c6d0f76272cd7 有些朋友要通過自己的網站后臺&#xff0c;包括論壇&#xff0c;來上傳一些文件&#xff0c;php一般為2m&#xff0c;或8m&#xff08;以下我們按默認為2m&#xff09;&#xff0c;接下來就是來…

移動硬盤格式化(pc和mac共用)-菜鳥級解決方案[轉]

用pc的時候買了一個320G的移動硬盤&#xff0c;從來沒考慮過什么格式化的問題&#xff0c;插上就用了。 后來接觸mac才發現pc和mac在移動存儲設備的格式化上還是有不少沖突的。如果你的移動硬盤mac上不能修改&#xff0c;或者pc上找不到&#xff0c;那就盡情得批判萬惡的資本主…

【php】php的ssh2擴展的安裝

ssh2(secure shell2)&#xff0c;對于遠端主機提供高安全性的資料傳輸工作。安裝&#xff1a;1、首先要裝OpenSSL。 2、要安裝 libssh2../configure && make all install3、再然后&#xff0c;安裝PECL/ssh2可以使用 pear install ssh2安裝&#xff08;有的說是 pear i…

回答知乎問題:你寫過什么自認為驚艷的詩?

首次整理于 2019-07-27 22:04:00&#xff0c;現在整理發布在公眾號申明原創。整理了一下大學期間2012年&#xff5e;2016年發布在QQ空間&#xff0c;自己感覺寫得還行的七首“詩詞”。回答知乎問題&#xff1a;你寫過什么自認為驚艷的詩&#xff1f;中國古詩詞博大精深。小時候…

lighttpd安裝配置支持php

轉載鏈接&#xff1a;https://wiki.freebsdchina.org/howto/n/php_fastcgi_lighttpd 安裝lighttpd 記得在SPAWNFCGI前打勾 [X] SPAWNFCGI Depend on spawn-fcgi utility #cd /usr/ports/www/lighttpd #make config #make install clean 安裝php 模塊自己看自己需要 #cd /usr/p…

密碼可逆不可逆選擇_膝關節損傷不可逆!跑步要注意!

膝蓋同時也是運動者最常受傷的關節。根據美國運動醫學整型外科協會的報告&#xff0c;美國每年約有三百萬人拉傷、挫傷、或扭傷他們的膝部&#xff0c;其中約有一半是因為運動引起的。而對于跑者而言&#xff0c;影響最大的就是我們的膝關節。換言之&#xff0c;長跑的潛在危害…

MS CRM 2011 C#中獲取Web Resource

原創地址&#xff1a;http://www.cnblogs.com/jfzhu/archive/2013/02/15/2913077.html 轉載請注明出處 我在以前的文章中講過如何用JScript讀取web resource資源&#xff0c;我在本文中將要講解如何在C#中獲取web resource資源。 有時候可能有這樣的需求&#xff0c;你需要在一…

測試驅動開發

測試驅動開發: 測試驅動開發&#xff08;Test Driven Development,英文縮寫TDD&#xff09;是極限編程的一個重要組成部分&#xff0c;它的基本思想就是在開發功能代碼之前&#xff0c;先編寫測試代碼。也就是說在明確要開發某個功能后&#xff0c;首先思考如何對這個功能進行測…