這里給大家分享我在網上總結出來的一些知識,希望對大家有所幫助

1. 定義整體結構
- 先寫出建構式,將Promise向外暴露
/*
自定義Promise函式模塊:IIFE
*/
(function (window) {
/*
Promise建構式
executor:執行器函式
*/
function Promise(executor) {
}
// 向外暴露Promise
window.Promise = Promise
})()
- 添加Promise原型物件上的方法
/*
Promise原型物件的then
指定一個成功/失敗的回呼函式
回傳一個新的promise物件
*/
Promise.prototype.then = function(onResolved,onRejected){
}
/*
Promise原型物件的.catch
指定一個失敗的回呼函式
回傳一個新的promise物件
*/
Promise.prototype.catch = function(onRejected){
}
- 添加Promise函式物件上的方法
/*
Promise函式物件的resovle方法
回傳一個指定結果的promise物件
*/
Promise.resolve = function(value){
}
/*
Promise函式物件的reject方法
回傳一個指定reason的失敗狀態的promise物件
*/
Promise.reject = function(value){
}
/*
Promise函式物件的all方法
回傳一個promise物件,只有當所有promise都成功時回傳的promise狀態才成功
*/
Promise.all = function(0value){
}
/*
Promise函式物件的race方法
回傳一個promise物件,狀態由第一個完成的promise決定
*/
Promise.race = function(value){
}
通過上面的注釋可以知道,不管是Promise原型物件上的方法還是Promise函式物件上的方法 ,它們的執行結果都將回傳一個Promise物件
2. 實作Promise建構式
我們看看我們是怎么使用Promise的
const promiseA = new Promise( (resolve,reject) => {
resolve(777);
});
- 我們傳入了一個函式,而且這個函式被立即執行,不僅如此,這個函式還會立即執行resolve和reject,說明建構式里有resolve和reject方法,因此我們可以初步實作:
/*
Promise建構式
executor:執行器函式
*/
function Promise(executor) {
function resovle() {
}
function reject() {
}
// 立即同步執行executor
executor(resovle,reject)
}
- 每個promise都有一個狀態可能為pending或resolved,rejected,而且初始狀態都為pending,因此需要添加個status來表示當前promise的狀態.,并且每個promise有自己的data,
function Promise(executor) {
var self = self
新增代碼
self.status = 'pending' // 給promise物件指定status屬性,初始值為pending
self.data = https://www.cnblogs.com/smileZAZ/archive/2022/09/21/undefined // 給promise物件指定一個存盤結果的data
function resovle() {
}
function reject() {
}
// 立即同步執行executor
executor(resovle,reject)
}
此外,當我們這樣使用Promise的時候,
// 例1
var promise = new Promise((resovle,reject)=>{
})
promise.then(resolve=>{},reject=>{})
這時執行到then,因為我們傳入的立即執行函式沒有執行resolve或者reject,所以promise的狀態還是pending,這時要把then里面的回呼函式保存起來,所以需要個callbacks陣列
function Promise(executor) {
var self = self
self.status = 'pending' // 給promise物件指定status屬性,初始值為pending
self.data = https://www.cnblogs.com/smileZAZ/archive/2022/09/21/undefined // 給promise物件指定一個存盤結果的data
新增代碼
self.callbacks = [] // 每個元素的結構:{onResolved(){},onRejected(){}}
function resovle() {
}
function reject() {
}
// 立即同步執行executor
executor(resovle,reject)
}
那 then函式是怎么把傳入的回呼收集起來的,其實很簡單,就是判斷當前promise是否為pending狀態,是的話,就把回呼push到callbacks中,
Promise.prototype.then = function(onResolved,onRejected){
var self = this
if(self.status === 'pending'){
// promise當前狀態還是pending狀態,將回呼函式保存起來
self.callbacks.push({
onResolved(){onResolved(self.data)},
onRejected(){onRejected(self.data)}
})
}else if(self.status === 'resolved'){
}else{
}
}
- 在上面的例子1的基礎上,當我們執行resovle(value)時,如例2
// 例2
var promise = new Promise((resolve,reject)=>{
setTimeout(function () {
resolve(1)
})
})
promise.then(
value=https://www.cnblogs.com/smileZAZ/archive/2022/09/21/>{console.log(value)},
err=>{console.log(err)}
)
此時代碼執行情況是怎么樣的呢?
- 先執行new Promise里的代碼,然后發現個定時器,js執行緒將定時器交給定時器執行緒處理,2. 然后繼續執行下面的代碼,發現是then,而且當前的promise還是pending的狀態,就把then里的回呼函式放到callbacks中,
- 5秒后定時器執行緒將定時器里的回呼函式(也就是宏任務)放到訊息佇列中,js執行緒在訊息佇列里發現了這個宏任務,就把它拿來執行,
- 執行這個宏任務,就執行了resolve(1),此時promise的callbacks里的回呼被執行,并將當前promise狀態改為resolved,然后這個1也會被保存到當前promise物件中
那怎么實作resolve呢?依舊上面的描述,就知道resovle的功能是執行callbacks里的函式,并保存data,并將當前promise狀態改為resolved,所以我們可以這么實作
function resolve(value) {
// 將狀態改為resolved
self.status = 'resolved'
// 保存value的值
self.data = https://www.cnblogs.com/smileZAZ/archive/2022/09/21/value
// 如果有待執行的callback函式,立即異步執行回呼函式onResolved
if (self.callbacks.length>0){
self.callbacks.forEach(callbackObj=>{
callbackObj.onResolved(value)
})
}
}
- 我們還知道,promise的狀態只能改變一次,因此當執行resolve的時候要判斷是不是promise是不是pending的狀態,否則是不能執行的
function resolve(value) {
// 如果當前狀態不是pending,則不執行
if(this.status !== 'pending'){
return
}
// 將狀態改為resolved
this.status = 'resolved'
// 保存value的值
this.data = https://www.cnblogs.com/smileZAZ/archive/2022/09/21/value
// 如果有待執行的callback函式,立即異步執行回呼函式onResolved
if (this.callbacks.length>0){
setTimeout(()=>{
this.callbacks.forEach(callbackObj=>{ A
callbackObj.onResolved(value)
})
})
}
}
- 異曲同工之妙的是reject方法也是這個道理,因此這里無需贅述
function reject(value) {
// 如果當前狀態不是pending,則不執行
if(self.status !== 'pending'){
return
}
// 將狀態改為rejected
self.status = 'rejected'
// 保存value的值
self.data = https://www.cnblogs.com/smileZAZ/archive/2022/09/21/value
// 如果有待執行的callback函式,立即異步執行回呼函式onResolved
if (self.callbacks.length>0){
self.callbacks.forEach(callbackObj=>{
callbackObj.onRejected(value)
})
}
}
- 我們又知道,當在執行executor的時候,如果執行例外的話,這個promise的狀態會直接執行reject方法,例如
// 例 3
var promise = new Promise((resolve,reject)=>{
error;執行到這里出錯了
setTimeout(function () {
resolve(1)
})
})
要實作這個功能,我們可以在executor外讓try catch來捕獲
try{
// 立即同步執行executor
executor(resolve,reject)
}catch (e) { // 如果執行器拋出例外,promise物件變為rejected狀態
reject(e)
}
好了,現在測驗下
// 例4
let promise = new Promise((resolve,reject)=>{
setTimeout(function () {
resolve(1)
//reject(1)
},100)
})
promise.then(
value=https://www.cnblogs.com/smileZAZ/archive/2022/09/21/>{
console.log("onResolved:",value);
},
reason=>{
console.log("onRejected:",reason);
}
)
發現成功, 成功輸出onResolved:1
3. 實作then方法
我們在上面簡單的實作了當前promise為pending狀態的情況,如:
Promise.prototype.then = function(onResolved,onRejected){
var self = this
if(self.status === 'pending'){
// promise當前狀態還是pending狀態,將回呼函式保存起來
self.callbacks.push({
onResolved(){onResolved(self.data)},
onRejected(){onRejected(self.data)}
})
}else if(self.status === 'resolved'){
}else{
}
}
那其他情況呢?
執行到then時,promise可能會是pending狀態,此時就要把then里的回呼函式保存起來,也可能會是resolved或者rejected狀態,此時就不用把回呼保存起來,直接執行onResolved或onRejected方法,注意是異步執行,而且是做為微任務的,這里我們簡單的用setTimeout來實作就好了,
Promise.prototype.then = function(onResolved,onRejected){
var self = this
if(self.status === 'pending'){
// promise當前狀態還是pending狀態,將回呼函式保存起來
self.callbacks.push({
onResolved(){onResolved(self.data)},
onRejected(){onRejected(self.data)}
})
}else if(self.status === 'resolved'){
setTimeout(()=>{
onResolved(self.data)
})
}else{
setTimeout(()=>{
onResolved(self.data)
})
}
}
而且我們知道,執行完then是要回傳一個新的promise的,而新的promise的狀態則由當前then的執行結果來確定,
Promise.prototype.then = function(onResolved,onRejected){
var self = this
return new Promise((resolve,reject)=>{
if(self.status === 'pending'){
// promise當前狀態還是pending狀態,將回呼函式保存起來
self.callbacks.push({
onResolved(){onResolved(self.data)},
onRejected(){onRejected(self.data)}
})
}else if(self.status === 'resolved'){
setTimeout(()=>{
onResolved(self.data)
})
}else{
setTimeout(()=>{
onResolved(self.data)
})
}
})
}
當 當前的promise狀態為resolved的時候,則執行then的時候,會執行第二個判斷陳述句
則當前執行第二個判斷陳述句的時候會出現三種情況
- 如果then里的回呼函式回傳的不是promise,return的新promise的狀態是則是resolved,value就是回傳的值,例如:
// 例5
let promise = new Promise((resolve,reject)=>{
resolve(1)
})
promise.then(
value=https://www.cnblogs.com/smileZAZ/archive/2022/09/21/>{
return value //回傳的不是promise,是value
}
)
因此,我們可以這樣實作
Promise.prototype.then = function(onResolved,onRejected){
var self = this
return new Promise((resolve,reject)=>{
if(self.status === 'pending'){
// promise當前狀態還是pending狀態,將回呼函式保存起來
self.callbacks.push({
onResolved(){onResolved(self.data)},
onRejected(){onRejected(self.data)}
})
}else if(self.status === 'resolved'){
修改代碼
setTimeout(()=>{
const result = onResolved(self.data)
if (result instanceof Promise){
} else {
// 1. 如果回呼函式回傳的不是promise,return的promise的狀態是resolved,value就是回傳的值,
resolve(result)
}
})
}else{
setTimeout(()=>{
onResolved(self.data)
})
}
})
}
簡單解釋下:
執行onResolved(self.data),其實就是執行例子中的下面這個回呼函式
value=https://www.cnblogs.com/smileZAZ/archive/2022/09/21/>{
return value //回傳的不是promise,是value
}
那么這個回呼函式回傳了value,就把value傳入resolve函式,resolve函式將當前新的promise的狀態改為resolved,同時將value保存到當前新的promise的data中,
- 如果回呼函式回傳的是promise,return的promise的結果就是這個promise的結果,如代碼所示,我們回傳一個新的promise,如果這個promise執行了resolve,回傳的新的promise的狀態則是resolved的,否則為rejected
// 例6
let promise = new Promise((resolve,reject)=>{
resolve(1)
})
promise.then(
value=https://www.cnblogs.com/smileZAZ/archive/2022/09/21/>{
return new Promise((resolve,reject)=>{
resolve(2)
//或者
//reject(error)
})
}
)
因此我們可以這樣實作
Promise.prototype.then = function(onResolved,onRejected){
var self = this
return new Promise((resolve,reject)=>{
if(self.status === 'pending'){
// promise當前狀態還是pending狀態,將回呼函式保存起來
self.callbacks.push({
onResolved(){onResolved(self.data)},
onRejected(){onRejected(self.data)}
})
}else if(self.status === 'resolved'){
setTimeout(()=>{
const result = onResolved(self.data)
if (result instanceof Promise){
// 2. 如果回呼函式回傳的是promise,return的promise的結果就是這個promise的結果
result.then(
value =https://www.cnblogs.com/smileZAZ/archive/2022/09/21/> {resolve(value)},
reason => {reject(reason)}
)
} else {
// 1. 如果回呼函式回傳的不是promise,return的promise的狀態是resolved,value就是回傳的值,
resolve(result)
}
})
}else{
setTimeout(()=>{
onResolved(self.data)
})
}
})
}
在這里說明一下:
result.then(
value =https://www.cnblogs.com/smileZAZ/archive/2022/09/21/> {resolve(value)},
reason => {reject(reason)}
)
由于我們在例6中執行了then里的
value=https://www.cnblogs.com/smileZAZ/archive/2022/09/21/>{
return new Promise((resolve,reject)=>{
resolve(2)
//或者
//reject(error)
})
}
則回傳一個promise物件,這個promise物件可能為resolved狀態(執行 resolve(2))也可能為rejected狀態(執行reject(error)),
將會導致value =https://www.cnblogs.com/smileZAZ/archive/2022/09/21/> {resolve(value)},這個回呼函式的執行或者 reason => {reject(reason)}的執行,
因此會把即將回傳的新的promise的data設定為value或者,reason,會把狀態設定為resolved或者rejected,
- 如果執行這段代碼的時候拋出錯誤,則回傳的promise的狀態為rejected,我們可以用try catch來實作
setTimeout(()=>{
try{
const result = onResolved(self.data)
if (result instanceof Promise){
// 2. 如果回呼函式回傳的是promise,return的promise的結果就是這個promise的結果
result.then(
value =https://www.cnblogs.com/smileZAZ/archive/2022/09/21/> {resolve(value)},
reason => {reject(reason)}
)
} else {
// 1. 如果回呼函式回傳的不是promise,return的promise的狀態是resolved,value就是回傳的值,
resolve(result)
}
}catch (e) {
// 3.如果執行onResolved的時候拋出錯誤,則回傳的promise的狀態為rejected
reject(e)
}
})
異曲同工之妙的是當status === 'rejected',道理一樣
setTimeout(()=>{
try{
const result = onRejected(self.data)
if (result instanceof Promise){
// 2. 如果回呼函式回傳的是promise,return的promise的結果就是這個promise的結果
result.then(
value =https://www.cnblogs.com/smileZAZ/archive/2022/09/21/> {resolve(value)},
reason => {reject(reason)}
)
} else {
// 1. 如果回呼函式回傳的不是promise,return的promise的狀態是resolved,value就是回傳的值,
resolve(result)
}
}catch (e) {
// 3.如果執行onResolved的時候拋出錯誤,則回傳的promise的狀態為rejected
reject(e)
}
})
到這里,我們發現當執行resolve的時候,onResolved(self.data)和onRejected(self.data)執行時也會跟上面一樣的結果,可以說執行回呼函式都要做以上判斷,因此我們要將
self.callbacks.push({
onResolved(){onResolved(self.data)},
onRejected(){onRejected(self.data)}
})
改成
if(self.status === 'pending'){
// promise當前狀態還是pending狀態,將回呼函式保存起來
self.callbacks.push({
onResolved(){
try{
const result = onResolved(self.data)
if (result instanceof Promise){
// 2. 如果回呼函式回傳的是promise,return的promise的結果就是這個promise的結果
result.then(
value =https://www.cnblogs.com/smileZAZ/archive/2022/09/21/> {resolve(value)},
reason => {reject(reason)}
)
} else {
// 1. 如果回呼函式回傳的不是promise,return的promise的狀態是resolved,value就是回傳的值,
resolve(result)
}
}catch (e) {
// 3.如果執行onResolved的時候拋出錯誤,則回傳的promise的狀態為rejected
reject(e)
}
},
到此,我們發現,相同的代碼太多了,因此有必要封裝一下
function handle(callback) {
try{
const result = callback(self.data)
if (result instanceof Promise){
// 2. 如果回呼函式回傳的是promise,return的promise的結果就是這個promise的結果
result.then(
value =https://www.cnblogs.com/smileZAZ/archive/2022/09/21/> {resolve(value)},
reason => {reject(reason)}
)
} else {
// 1. 如果回呼函式回傳的不是promise,return的promise的狀態是resolved,value就是回傳的值,
resolve(result)
}
}catch (e) {
// 3.如果執行onResolved的時候拋出錯誤,則回傳的promise的狀態為rejected
reject(e)
}
}
這樣以來就清爽了很多
Promise.prototype.then = function(onResolved,onRejected){
var self = this
return new Promise((resolve,reject)=>{
/*
呼叫指定回呼函式的處理,根據執行結果,改變return的promise狀態
*/
function handle(callback) {
try{
const result = callback(self.data)
if (result instanceof Promise){
// 2. 如果回呼函式回傳的是promise,return的promise的結果就是這個promise的結果
result.then(
value =https://www.cnblogs.com/smileZAZ/archive/2022/09/21/> {resolve(value)},
reason => {reject(reason)}
)
} else {
// 1. 如果回呼函式回傳的不是promise,return的promise的狀態是resolved,value就是回傳的值,
resolve(result)
}
}catch (e) {
// 3.如果執行onResolved的時候拋出錯誤,則回傳的promise的狀態為rejected
reject(e)
}
}
if(self.status ==='pending'){
// promise當前狀態還是pending狀態,將回呼函式保存起來
self.callbacks.push({
onResolved(){
handle(onResolved)
},
onRejected(){
handle(onRejected)
}
})
}else if(self.status === 'resolved'){
setTimeout(()=>{
handle(onResolved)
})
}else{ // 當status === 'rejected'
setTimeout(()=>{
handle(onRejected)
})
}
})
}
另外,我們還知道,promise會發生值傳透,例如
let promsie = new Promise((resolve,reject)=>{
resolve(1)
})
promsie
.then(2)
.then(3)
.then(value =https://www.cnblogs.com/smileZAZ/archive/2022/09/21/>console.log(value))
運行結果: 1
解釋:.then 或者 .catch 的引數期望是函式,傳入非函式則會發生值穿透,值傳透可以理解為,當傳入then的不是函式的時候,這個then是無效的,而實際原理上其實是當then中傳入的不算函式,則這個then回傳的promise的data,將會保存上一個的promise.data,這就是發生值穿透的原因,而且每一個無效的then所回傳的promise的狀態都為resolved,
因此,要實作直傳透這個特性,我們可以這樣實作
添加這兩句來判斷要不要發生值傳透
onResolved = typeof onResolved === 'function'? onResolved: value =https://www.cnblogs.com/smileZAZ/archive/2022/09/21/> value
onRejected = typeof onRejected ==='function'? onRejected: reason => {throw reason}
實際上就是改寫,如果傳入的不是函式,那就忽略那個傳入值,自己再寫一個函式,這個函式的執行結果將回傳上一個promise的data
Promise.prototype.then = function(onResolved,onRejected){
onResolved = typeof onResolved === 'function'? onResolved: value =https://www.cnblogs.com/smileZAZ/archive/2022/09/21/> value
onRejected = typeof onRejected ==='function'? onRejected: reason => {throw reason}
var self = this
return new Promise((resolve,reject)=>{
/*
呼叫指定回呼函式的處理,根據執行結果,改變return的promise狀態
*/
function handle(callback) {
try{
const result = callback(self.data)
if (result instanceof Promise){
// 2. 如果回呼函式回傳的是promise,return的promise的結果就是這個promise的結果
result.then(
value =https://www.cnblogs.com/smileZAZ/archive/2022/09/21/> {resolve(value)},
reason => {reject(reason)}
)
} else {
// 1. 如果回呼函式回傳的不是promise,return的promise的狀態是resolved,value就是回傳的值,
resolve(result)
}
}catch (e) {
// 3.如果執行onResolved的時候拋出錯誤,則回傳的promise的狀態為rejected
reject(e)
}
}
if(self.status ==='pending'){
// promise當前狀態還是pending狀態,將回呼函式保存起來
self.callbacks.push({
onResolved(){
handle(onResolved)
},
onRejected(){
handle(onRejected)
}
})
}else if(self.status === 'resolved'){
setTimeout(()=>{
handle(onResolved)
})
}else{ // 當status === 'rejected'
setTimeout(()=>{
handle(onRejected)
})
}
})
}
3.實作catch方法
catch方法的作用跟then里的第二歌回呼函式一樣,因此我們可以這樣來實作
Promise.prototype.catch = function(onRejected){
return this.then(undefined,onRejected)
}
我的天啊,居然這么簡單
4. 實作Promise.resolve
我們都知道,Promise.resolve方法可以傳三種值
- 不是promise
- 成功狀態的promise
- 失敗狀態的promise
Promise.resolve(1)
Promise.resolve(Promise.resolve(1))
Promise.resolve(Promise.reject(1))
實際上跟實作上面的then時有點像
Promise.resolve = function(value){
return new Promise((resolve,reject)=>{
if (value instanceof Promise){
// 如果value 是promise
value.then(
value =https://www.cnblogs.com/smileZAZ/archive/2022/09/21/> {resolve(value)},
reason => {reject(reason)}
)
} else{
// 如果value不是promise
resolve(value)
}
}
}
5.實作Promise.reject
實作這個比較簡單,回傳一個狀態為rejected的promise就好了
/*
Promise函式物件的reject方法
回傳一個指定reason的失敗狀態的promise物件
*/
Promise.reject = function(reason){
return new Promise((resolve,reject)=>{
reject(reason)
})
}
6.實作Promise.all
我們知道,這個方法會回傳一個promise
/*
Promise函式物件的all方法
回傳一個promise物件,只有當所有promise都成功時回傳的promise狀態才成功
*/
Promise.all = function(promises){
return new Promise((resolve,reject)=>{
})
}
而這個promise的狀態由遍歷每個promise產生的結果決定
/*
Promise函式物件的all方法
回傳一個promise物件,只有當所有promise都成功時回傳的promise狀態才成功
*/
Promise.all = function(promises){
return new Promise((resolve,reject)=>{
// 遍歷promises,獲取每個promise的結果
promises.forEach((p,index)=>{
})
})
}
有兩種結果:
- 遍歷到有一個promise是reject狀態,則直接回傳的promise狀態為rejected
Promise.all = function(promises){
return new Promise((resolve,reject)=>{
// 遍歷promises,獲取每個promise的結果
promises.forEach((p,index)=>{
p.then(
value =https://www.cnblogs.com/smileZAZ/archive/2022/09/21/> {
},
reason => { //只要有一個失敗,return的promise狀態就為reject
reject(reason)
}
)
})
})
}
- 遍歷所有的promise的狀態都為resolved,則回傳的promise狀態為resolved,并且還要每個promise產生的值傳遞下去
Promise.all = function(promises){
const values = new Array(promises.length)
var resolvedCount = 0 //計狀態為resolved的promise的數量
return new Promise((resolve,reject)=>{
// 遍歷promises,獲取每個promise的結果
promises.forEach((p,index)=>{
p.then(
value =https://www.cnblogs.com/smileZAZ/archive/2022/09/21/> {
// p狀態為resolved,將值保存起來
values[index] = value
resolvedCount++;
// 如果全部p都為resolved狀態,return的promise狀態為resolved
if(resolvedCount === promises.length){
resolve(values)
}
},
reason => { //只要有一個失敗,return的promise狀態就為reject
reject(reason)
}
)
})
})
}
好像可以了,當其實這里還有一個問題,就是all傳進去的陣列不一定都是promise物件,可能是這樣的
all([p,2,3,p])
因此需要把不是promise的數字包裝成promise
Promise.all = function(promises){
const values = new Array(promises.length)
var resolvedCount = 0 //計狀態為resolved的promise的數量
return new Promise((resolve,reject)=>{
// 遍歷promises,獲取每個promise的結果
promises.forEach((p,index)=>{
Promise.resolve(p).then(
value =https://www.cnblogs.com/smileZAZ/archive/2022/09/21/> {
// p狀態為resolved,將值保存起來
values[index] = value
resolvedCount++;
// 如果全部p都為resolved狀態,return的promise狀態為resolved
if(resolvedCount === promises.length){
resolve(values)
}
},
reason => { //只要有一個失敗,return的promise狀態就為reject
reject(reason)
}
)
})
})
}
7.實作Promise.race
這個方法的實作要比all簡單很多
/*
Promise函式物件的race方法
回傳一個promise物件,狀態由第一個完成的promise決定
*/
Promise.race = function(promises){
return new Promise((resolve,reject)=>{
// 遍歷promises,獲取每個promise的結果
promises.forEach((p,index)=>{
Promise.resolve(p).then(
value =https://www.cnblogs.com/smileZAZ/archive/2022/09/21/> {
// 只要有一個成功,回傳的promise的狀態九尾resolved
resolve(value)
},
reason => { //只要有一個失敗,return的promise狀態就為reject
reject(reason)
}
)
})
})
}
本文轉載于:
https://juejin.cn/post/6856213486633304078
如果對您有所幫助,歡迎您點個關注,我會定時更新技術檔案,大家一起討論學習,一起進步,

轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/509274.html
標籤:其他
