摘要:類是由一個構(gòu)造函數(shù)和一個關(guān)聯(lián)的原型組成的一種設(shè)計(jì)模式。該模式的一個缺點(diǎn)是,為了讓構(gòu)造函數(shù)中的變量在使用它們的方法的作用域內(nèi),這些方法必須放置于實(shí)例對象中,這會導(dǎo)致方法副本的擴(kuò)散。
參考書籍:《Effective JavaScript》
對象和原型 理解prototype、getPrototypeOf和__proto__之間的不同原型包括三個獨(dú)立但相關(guān)的訪問器。
C.prototype用于建立由new C()創(chuàng)建的對象的原型。
Object.getPrototypeOf(obj)是ES5中用來獲取obj對象的原型對象的標(biāo)準(zhǔn)方法。
obj.__proto__是獲取obj對象的原型對象的非標(biāo)準(zhǔn)方法。
function User(name, passwordHash) { this.name = name; this.passwordHash = passwordHash; } User.prototype.toString = function () { return "[User " + this.name + "]"; }; User.prototype.checkPassword = function (password) { return hash(password) === this.passwordHash; } var u = new User("sfalken", "0ef33ae791068ec64b502d6cb0191387");
User函數(shù)帶有一個默認(rèn)的prototype屬性,其包含一個開始幾乎為空的對象。當(dāng)我們使用new操作符創(chuàng)建User的實(shí)例時,產(chǎn)生的對象u得到了自動分配的原型對象,該原型對象被存儲在User.prototype中。
Object.getPrototypeOf(u) === User.prototype; // true
u.__proto__ === User.prototype; // true
提示:
C.prototype屬性是new C()創(chuàng)建的對象的原型。
Object.getPrototypeOf(obj)是ES5中檢索對象原型的標(biāo)準(zhǔn)函數(shù)。
Obj.__proto__是檢索對象原型的非標(biāo)準(zhǔn)函數(shù)。
類是由一個構(gòu)造函數(shù)和一個關(guān)聯(lián)的原型組成的一種設(shè)計(jì)模式。
使用Object.getPrototypeOf函數(shù)而不要使用__proto__屬性__proto__屬性提供了Object.getPrototypeOf方法所不具備的額外能力,即修改對象原型鏈接的能力。這種能力會造成嚴(yán)重的影響,應(yīng)當(dāng)避免使用,原因如下:
可移植性:并不是所有的平臺都支持改變對象原型的特性,所以無法編寫可移植的代碼。
性能問題:現(xiàn)代的JavaScript引擎痘深度優(yōu)化了獲取和設(shè)置對象屬性的行為,如更改了對象的內(nèi)部結(jié)構(gòu)(如添加或刪除該對象或其原型鏈中的對象的屬性)會使一些優(yōu)化失效。
可預(yù)測性:修改對象的原型鏈會影響對象的整個繼承層次結(jié)構(gòu),在某些情況下這樣的操作可能有用,但是保持繼承層次結(jié)構(gòu)的相對穩(wěn)定是一個基本的準(zhǔn)則。
可以使用ES5中的Object.create函數(shù)來創(chuàng)建一個具有自定義原型鏈的新對象。
提示::
始終不要修改對象的__proto__屬性。
使用Object.create函數(shù)給新對象設(shè)置自定義的原型。
使構(gòu)造函數(shù)與new操作符無關(guān)function User(name, passwordHash) { this.name = name; this.passwordHash = passwordHash; } var u = User("baravelli", "d8b74df393528d51cd19980ae0aa028e"); u; // undefined this.name; // baravelli this.passwordHash; // d8b74df393528d51cd19980ae0aa028e
如果調(diào)用者忘記使用new關(guān)鍵字,該函數(shù)不但會返回?zé)o意義的undefined,而且會創(chuàng)建(如果這些全局變量已經(jīng)存在則會修改)全局變量name和passwordHash。
如果將User函數(shù)定義為ES5的嚴(yán)格代碼,那么它的接收者默認(rèn)為undefined。
function User(name, passwordHash) { "use strict"; this.name = name; this.passwordHash = passwordHash; } var u = User("baravelli", "d8b74df393528d51cd19980ae0aa028e"); // Uncaught TypeError: Cannot set property "name" of undefined
一個更為健壯的方式是提供一個不管怎么調(diào)用都工作如構(gòu)造函數(shù)的函數(shù)。
function User(name, passwordHash) { if (!this instanceof User) { return new User(name, passwordHash); } this.name = name; this.passwordHash = passwordHash; } var x = User("baravelli", "d8b74df393528d51cd19980ae0aa028e"); var y = new User("baravelli", "d8b74df393528d51cd19980ae0aa028e"); x instanceof User; // true y instanceof User; // true
上述模式的一個缺點(diǎn)是它需要額外的函數(shù)調(diào)用,且難適用于可變參數(shù)函數(shù),因?yàn)闆]有一種模擬apply方法將可變參數(shù)函數(shù)作為構(gòu)造函數(shù)調(diào)用的方式。
一種更為奇異的方式是利用ES5的Object.create函數(shù)。
function User(name, passwordHash) { var self = this instanceof User ? this : Object.create(User.prototype); self.name = name; self.passwordHash = passwordHash; return self; }
Object.create需要一個原型對象作為參數(shù),并返回一個繼承自原型對象的新對象。
多虧了構(gòu)造函數(shù)覆蓋模式,使用new操作符調(diào)用上述User函數(shù)的行為與以函數(shù)調(diào)用它的行為是一樣的,這能工作完全得益于JavaScript允許new表達(dá)式的結(jié)果可以被構(gòu)造函數(shù)的顯示return語句所覆蓋。
提示:
通過使用new操作符或Object.create方法在構(gòu)造函數(shù)定義中調(diào)用自身使得該構(gòu)造函數(shù)與調(diào)用語法無關(guān)。
當(dāng)一個函數(shù)期望使用new操作符調(diào)用時,清晰地文檔化該函數(shù)。
在原型中存儲方法JavaScript完全有可能不借助原型進(jìn)行編程。
function User(name, passwordHash) { this.name = name; this.passwordHash = passwordHash; this.toString = function () { return "User " + this.name + "]"; }; this.checkPassword = function (password) { return hash(password) === this.passwordHash; } } var u1 = new User(/* ... */); var u2 = new User(/* ... */); var u3 = new User(/* ... */);
上述代碼中的每個實(shí)例都包含toString和checkPassword方法的副本,而不是通過原型共享這些方法。
將方法存儲在原型,使其可以被所有的實(shí)例使用,而不需要存儲方法實(shí)現(xiàn)的多個副本,也不需要給每個實(shí)例對象增加額外的屬性。
同時,現(xiàn)代的JavaScript引擎深度優(yōu)化了原型查找,所以將方法復(fù)制到實(shí)例對象并不一定保證查找的速度有明顯的提升,而且實(shí)例方法比起原型方法肯定會占用更多的內(nèi)存。
提示:
將方法存儲在實(shí)例對象中會創(chuàng)建該函數(shù)的多個副本,因?yàn)槊總€實(shí)例對象都有一份副本。
將方法存儲于原型中優(yōu)于存儲在實(shí)例對象中。
使用閉包存儲私有數(shù)據(jù)任意一段程序都可以簡單地通過訪問JavaScript對象的屬性名來獲取相應(yīng)地對象屬性,例如for in循環(huán)、ES5的Object.keys函數(shù)和Object.getOwnPropertyNames函數(shù)。
一些程序員使用命名規(guī)范給私有屬性前置或后置一個下劃線字符_。
然而實(shí)際上,一些程序需要更高程度的信息隱藏。
對于這種情形,JavaScript為信息隱藏提供了閉包。閉包將數(shù)據(jù)存儲到封閉的變量中而不提供對這些變量的直接訪問,獲取閉包內(nèi)部結(jié)構(gòu)的唯一方式是該函數(shù)顯式地提供獲取它的途徑。
利用這一特性在對象中存儲真正的私有數(shù)據(jù)。不是將數(shù)據(jù)作為對象的屬性來存儲,而是在構(gòu)造函數(shù)中以變量的方式存儲它。
function User(name, passwordHash) { this.toString = function () { return "[User " + name + "]"; }; this.checkPassword = function (password) { return hash(password) === passwordHash; } }
上述代碼的toString和checkPassword方法是以變量的方式來引用name和passwordHash變量的,而不是以this屬性的方式來引用,User的實(shí)例不包含任何實(shí)例屬性,因此外部的代碼不能直接訪問User實(shí)例的name和passwordHash變量。
該模式的一個缺點(diǎn)是,為了讓構(gòu)造函數(shù)中的變量在使用它們的方法的作用域內(nèi),這些方法必須放置于實(shí)例對象中,這會導(dǎo)致方法副本的擴(kuò)散。
提示:
閉包變量是私有的,只能通過局部的引用獲取。
將局部變量作為私有數(shù)據(jù)從而通過方法實(shí)現(xiàn)信息隱藏。
只將實(shí)例狀態(tài)存儲在實(shí)例對象中一種錯誤的做法是不小心將每個實(shí)例的數(shù)據(jù)存儲到了其原型中。
function Tree(x) { this.value = x; } Tree.prototype = { children: [], // should be instance state! addChild: function(x) { this.children.push(x); } }; var left = new Tree(2); left.addChild(1); left.addChild(3); var right = new Tree(6); right.addChild(5); right.addChild(7); var top = new Tree(4); top.addChild(left); top.addChild(right); top.children; // [1, 3, 5, 7, left, right]
每次調(diào)用addChild方法,都會將值添加到Tree.prototype.children數(shù)組中。
實(shí)現(xiàn)Tree類的正確方式是為每個實(shí)例對象創(chuàng)建一個多帶帶的children數(shù)組。
function Tree(x) { this.value = x; this.children = []; // instance state } Tree.prototype = { addChild: function(x) { this.children.push(x); } };
一般情況下,任何不可變的數(shù)據(jù)可以被存儲在原型中從而被安全地共享。有狀態(tài)的數(shù)據(jù)原則上也可以存儲在原型中,只要你真正想共享它。然而迄今為止,在原型對象中最常見的數(shù)據(jù)是方法,而每個實(shí)例的狀態(tài)都存儲在實(shí)例對象中。
提示:
共享可變數(shù)據(jù)可能會出問題,因?yàn)樵褪潜黄渌械膶?shí)例共享的。
將可變的實(shí)例狀態(tài)存儲在實(shí)例對象中。
認(rèn)識到this變量的隱式綁定問題編寫一個簡單的、可定制的讀取CSV(逗號分隔型取值)數(shù)據(jù)的類。
function CSVReader(separators) { this.separators = separators || [","]; this.regexp = new RegExp(this.separators.map(function (sep) { return "" + sep[0]; }).join("|")); }
實(shí)現(xiàn)一個簡單的read方法可以分為兩步來處理。第一步,將輸入的字符串分為按行劃分的數(shù)組。第二步,將數(shù)組的每一行再分為按單元格劃分的數(shù)組。結(jié)果獲得一個二維的字符串?dāng)?shù)組。
CSVReader.prototype.read = function (str) { var lines = str.trim().split(/ /); return lines.map(function (line) { return line.split(this.regexp); }); }; var reader = new CSVReader(); reader.read("a, b, c d, e, f "); // [["a, b, c"], ["d, e, f"]]
上述代碼的bug是,傳遞給line.map的回調(diào)函數(shù)引用的this指向的是window,因此,this.regexp產(chǎn)生undefined值。
備注:"a, b, c".split(undefined)返回["a, b, c"]。
幸運(yùn)的是,數(shù)組的map方法可以傳入一個可選的參數(shù)作為其回調(diào)函數(shù)的this綁定。
CSVReader.prototype.read = function (str) { var lines = str.trim().split(/ /); return lines.map(function (line) { return line.split(this.regexp); }, this); }; var reader = new CSVReader(); reader.read("a, b, c d, e, f "); // [["a", "b", "c"], ["d", "e", "f"]]
但是,不是所有基于回調(diào)函數(shù)的API都考慮周全。另一種解決方案是使用詞法作用域的變量來存儲這個額外的外部this綁定的引用。
CSVReader.prototype.read = function (str) { var lines = str.trim().split(/ /); var self = this; // save a reference to outer this-binding return lines.map(function (line) { return line.split(this.regexp); }); }; var reader = new CSVReader(); reader.read("a, b, c d, e, f "); // [["a", "b", "c"], ["d", "e", "f"]]
在ES5的環(huán)境中,另一種有效的方法是使用回調(diào)函數(shù)的bind方法。
CSVReader.prototype.read = function (str) { var lines = str.trim().split(/ /); return lines.map(function (line) { return line.split(this.regexp); }.bind(this)); // bind to outer this-binding }; var reader = new CSVReader(); reader.read("a, b, c d, e, f "); // [["a", "b", "c"], ["d", "e", "f"]]
提示:
this變量的作用域總是由其最近的封閉函數(shù)所確定。
使用一個局部變量(通常命名為self、me或that)使得this綁定對于內(nèi)部函數(shù)是可用的。
在子類的構(gòu)造函數(shù)中調(diào)用父類的構(gòu)造函數(shù)場景圖(scene graph)是在可視化的程序中(如游戲或圖形仿真場景)描述一個場景的對象集合。一個簡單的場景包含了在該場景中的所有對象(稱為角色),以及所有角色的預(yù)加載圖像數(shù)據(jù)集,還包含一個底層圖形顯示的引用(通常被稱為context)。
function Scene(context, width, height, images) { this.context = context; this.width = width; this.height = height; this.images = images; this.actors = []; } Scene.prototype.register = function (actor) { this.actors.push(actor); }; Scene.prototype.unregister = function (actor) { var i = this.actors.indexOf(actor); if (i >= 0) { this.actors.splice(i, 1); } }; Scene.prototype.draw = function () { this.context.clearRect(0, 0, this.width, this.height); for (var a = this.actors, i = 0, n = a.length; i < n; i++) { a[i].draw(); } };
場景中的所有角色都繼承自基類Actor。
function Actor(scene, x, y) { this.scene = scene; this.x = x; this.y = y; scene.register(this); } Actor.prototype.moveTo = function (x, y) { this.x = x; this.y = y; this.scene.draw(); }; Actor.prototype.exit = function() { this.scene.unregister(this); this.scene.draw(); }; Actor.prototype.draw = function () { var image = this.scene.images[this.type]; this.scene.context.drawImage(image, this.x, this.y); }; Actor.prototype.width = function () { return this.scene.images[this.type].width; }; Actor.prototype.height = function () { return this.scene.images[this.type].height; };
我們將角色的特定類型實(shí)現(xiàn)為Actor的子類。例如,在街機(jī)游戲中太空飛船就會有一個拓展自Actor的SpaceShip類。
為了確保SpaceShip的實(shí)例能作為角色被正確地初始化,其構(gòu)造函數(shù)必須顯式地調(diào)用Actor的構(gòu)造函數(shù)。通過將接收者綁定到該新對象來調(diào)用Actor可以達(dá)到此目的。
function SpaceShip(scene, x, y) { Actor.call(this, scene, x, y); this.points = 0; }
調(diào)用Actor的構(gòu)造函數(shù)能確保Actor創(chuàng)建的所有實(shí)例屬性都被添加到了新對象(SpaceShip實(shí)例對象)中。為了使SpaceShip成為Actor的一個正確地子類,其原型必須繼承自Actor.prototype。做這種拓展的最好的方式是使用ES5提供的Object.create方法。
SpaceShip.prototype = Object.create(Actor.prototype);
一旦創(chuàng)建了SpaceShip的原型對象,我們就可以向其添加所有的可被實(shí)例共享的屬性。
SpaceShip.prototype.type = "spaceShip"; SpaceShip.prototype.scorePoint = function () { this.points++; }; SpaceShip.prototype.left = function () { this.moveTo(Math.max(this.x - 10, 0), this.y); }; SpaceShip.prototype.right = function () { var maxWidth = this.scene.width - this.width(); this.moveTo(Math.min(this.x + 10, maxWidth), this.y); };
提示:
在子類構(gòu)造函數(shù)中顯示地傳入this作為顯式地接收者調(diào)用父類構(gòu)造函數(shù)。
使用Object.create函數(shù)來構(gòu)造子類的原型對象以避免調(diào)用父類的構(gòu)造函數(shù)。
不要重用父類的屬性名function Actor(scene, x, y) { this.scene = scene; this.x = x; this.y = y; this.id = ++Actor.nextID; scene.register(this); } Actor.nextID = 0;
function Alien(scene, x, y, direction, speed, strength) { Actor.call(this, scene, x, y); this.direction = direction; this.speed = speed; this.strength = strength; this.damage = 0; this.id = ++Alien.nextID; // conflicts with actor id! } Alien.nextID = 0;
Alien類與其父類Actor類都視圖給實(shí)例屬性id寫數(shù)據(jù)。如果在繼承體系中的兩個類指向相同的屬性名,那么它們指向的是同一個屬性。
該例子顯而易見的解決方法是對Actor標(biāo)識數(shù)和Alien標(biāo)識數(shù)使用不同的屬性名。
function Actor(scene, x, y) { this.scene = scene; this.x = x; this.y = y; this.actorID = ++Actor.nextID; // distinct from alienID scene.register(this); } Actor.nextID = 0; function Alien(scene, x, y, direction, speed, strength) { Actor.call(this, scene, x, y); this.direction = direction; this.speed = speed; this.strength = strength; this.damage = 0; this.alienID = ++Alien.nextID; // distinct from actorID } Alien.nextID = 0;
提示:
留意父類使用的所有屬性名。
不要在子類中重用父類的屬性名。
避免繼承標(biāo)準(zhǔn)類一個操作文件系統(tǒng)的庫可能希望創(chuàng)建一個抽象的目錄,該目錄繼承了數(shù)組的所有行為。
function Dir(path, entries) { this.path = path; for (var i = 0, n = entries.length; i < n; i++) { this[i] = entries[i]; } } Dir.prototype = Object.create(Array.prototype); // extends Array
遺憾的是,這種方式破壞了數(shù)組的length屬性的預(yù)期行為。
var dir = new Dir("/tmp/mysite", ["index.html", "script.js", "style.css"]); dir.length; // 0
失敗的原因是length屬性只對在內(nèi)部標(biāo)記為“真正的”數(shù)組的特殊對象起作用。ECMAScript標(biāo)準(zhǔn)規(guī)定它是一個不可見的內(nèi)部屬性,稱為[[Class]]。
數(shù)組對象(通過Array構(gòu)造函數(shù)或[]語法創(chuàng)建)被加上了值為“Array”的[[Class]]屬性,函數(shù)被加上了值為“Function”的[[Class]]屬性。
事實(shí)證明,length的行為只被定義在內(nèi)部屬性[[Class]]的值為“Array”的特殊對象中。對于這些對象,JavaScript保持length屬性與該對象的索引屬性的數(shù)量同步。
但當(dāng)我們拓展Array類時,子類的實(shí)例并不是通過new Array()或字面量[]語法創(chuàng)建的。所以,Dir的實(shí)例[[Class]]屬性值為“Object”。
更好的實(shí)現(xiàn)是定義一個entries數(shù)組的實(shí)例屬性。
function Dir(path, entries) { this.path = path; this.entries = entries; // array property } Dir.prototype.forEach = function (f, thisArg) { if (typeof thisArg === "undefined") { thisArg = this; } this.entries.forEach(f, thisArg); };
提示:
繼承標(biāo)準(zhǔn)類往往由于一些特殊的內(nèi)部屬性(如[[Class]])而被破壞。
使用屬性委托優(yōu)于繼承標(biāo)準(zhǔn)類。
將原型視為實(shí)現(xiàn)細(xì)節(jié)原型是一種對象行為的實(shí)現(xiàn)細(xì)節(jié)。
JavaScript提供了便利的內(nèi)省機(jī)制(introspection mechanisms)來檢查對象的細(xì)節(jié)。Object.prototype.hasOwnProperty方法確定一個屬性是否為對象“自己的”屬性(即一個實(shí)例屬性),而完全忽略原型繼承機(jī)構(gòu)。Object.getPrototypeOf和__proto__特性允許程序員遍歷對象的原型鏈并多帶帶查詢其原型對象。
檢查實(shí)現(xiàn)細(xì)節(jié)(即使沒有修改它們)也會在程序的組件之間創(chuàng)建依賴。如果對象的生產(chǎn)者修改了實(shí)現(xiàn)細(xì)節(jié),那么依賴于這些對象的使用者就會被破壞。
提示:
對象是接口,原型是實(shí)現(xiàn)。
避免檢查你無法控制的對象的原型結(jié)構(gòu)。
避免檢查實(shí)現(xiàn)在你無法控制的對象內(nèi)部的屬性。
避免使用輕率的猴子補(bǔ)丁由于對象共享原型,因此每一個對象都可以增加、刪除或修改原型的屬性,這個有爭議的實(shí)踐通常被稱為猴子補(bǔ)丁(monkey-patching)。
猴子補(bǔ)丁的吸引力在于它的強(qiáng)大,數(shù)組缺少一個有用的方法,你自己就可以增加它。
Array.prototype.split = function (i) { // alternative #1 return [this.slice(0, 1), this.slice(i)]; };
但是當(dāng)多個庫以不兼容的方式給同一個原型打猴子補(bǔ)丁時,問題就出現(xiàn)了。
Array.prototype.split = function (i) { // alternative #2 var i = Math.floor(this.length / 2); return [this.slice(0, 1), this.slice(i)]; };
現(xiàn)在,任一對數(shù)組split方法的使用都大約有50%的機(jī)會被破壞。
一個方法可以將這些修改置于一個函數(shù)中,用戶可以選擇調(diào)用或忽略。
function addArrayMethods() { Array.prototype.split = function (i) { return [this.slice(0, 1), this.slice(i)]; } }
盡管猴子補(bǔ)丁很危險(xiǎn),但是有一種特別可靠而且有價值的使用場景:polyfill。
if (typeof Array.prototype.map !== "function") { Array.prototype.map = function (f, thisArg) { var result = []; for (var i = 0, n = this.length; i < n; i++) { result[i] = f.call(thisArg, this[i], i); } return result; }; }
提示:
避免使用輕率的猴子補(bǔ)丁。
記錄程序庫所執(zhí)行的所有猴子補(bǔ)丁。
考慮通過將修改置于一個到處函數(shù)中,使猴子補(bǔ)丁稱為可選的。
使用猴子補(bǔ)丁為缺失的標(biāo)準(zhǔn)API提供polyfills。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/107678.html
摘要:但實(shí)例化該構(gòu)造函數(shù)仍然得到的是的實(shí)例。或者,為了避免在所有查找屬性的地方都插入這段樣本代碼,我們可以將該模式抽象到的構(gòu)造函數(shù)中。該構(gòu)造函數(shù)封裝了所有在單一數(shù)據(jù)類型定義中編寫健壯字典的技術(shù)細(xì)節(jié)。 參考書籍:《Effective JavaScript》 數(shù)組和字典 對象是JavaScript中最萬能的數(shù)據(jù)結(jié)構(gòu)。取決于不同的環(huán)境,對象可以表示一個靈活的鍵值關(guān)聯(lián)記錄,一個繼承了方法的面向?qū)ο髷?shù)...
摘要:五不要增加內(nèi)置的原型增加內(nèi)置構(gòu)造函數(shù)如,和等的原型屬性是一個增強(qiáng)功能性的強(qiáng)大的方法,但這可能會嚴(yán)重影響可維護(hù)性,因?yàn)檫@種做法將使代碼變得更加不可預(yù)測。推薦使用后者,這樣根據(jù)名字就能明顯地區(qū)分出變量函數(shù)和基本常量等。 一、盡量少用全局變量 減少全局名字空間污染,最理想的情況是一個應(yīng)用程序僅有一個全局變量。 二、單一var模式 var a = 1, b = 2, sum =...
摘要:訪問全局對象在瀏覽器中,全局對象可以通過屬性在代碼的任何位置訪問除非你做了些比較出格的事情,像是聲明了一個名為的局部變量。 前言 才華橫溢的Stoyan Stefanov,在他寫的由O’Reilly初版的新書《JavaScript Patterns》(JavaScript模式)中,我想要是為我們的讀者貢獻(xiàn)其摘要,那會是件很美妙的事情。具體一點(diǎn)就是編寫高質(zhì)量JavaScript的一些要素...
摘要:前言月份開始出沒社區(qū),現(xiàn)在差不多月了,按照工作的說法,就是差不多過了三個月的試用期,準(zhǔn)備轉(zhuǎn)正了一般來說,差不多到了轉(zhuǎn)正的時候,會進(jìn)行總結(jié)或者分享會議那么今天我就把看過的一些學(xué)習(xí)資源主要是博客,博文推薦分享給大家。 1.前言 6月份開始出沒社區(qū),現(xiàn)在差不多9月了,按照工作的說法,就是差不多過了三個月的試用期,準(zhǔn)備轉(zhuǎn)正了!一般來說,差不多到了轉(zhuǎn)正的時候,會進(jìn)行總結(jié)或者分享會議!那么今天我就...
閱讀 3522·2023-04-25 14:57
閱讀 2569·2021-11-22 14:56
閱讀 2092·2021-09-29 09:45
閱讀 1775·2021-09-22 15:53
閱讀 3325·2021-08-25 09:41
閱讀 907·2019-08-29 15:22
閱讀 3299·2019-08-29 13:22
閱讀 3130·2019-08-29 13:08