検索
ホームページウェブフロントエンドjsチュートリアルこの記事では、JavaScript のディープ コピーについて詳しく説明します。

この記事では、JavaScript のディープ コピーについて詳しく説明します。

ディープコピーに関する記事はインターネット上にたくさんありますが、質はさまざまで、よく考えられていないものも多く、書き方も比較的雑で満足のいくものではありません。この記事は 完璧なディープコピー を完成させることを目的としています。読んだ後に質問がある場合は、自由に追加および改善してください。

ディープ コピーが完了したかどうかを評価するには、次の質問が実装されているかどうかを確認してください:

  • 基本的な型データを実行できるかどうかコピーされる?

  • キーと値はどちらも基本的な型です通常のオブジェクトコピーできますか?

  • #シンボルオブジェクトのキーはコピーできますか?

  • Date および RegExp オブジェクト タイプはコピーできますか?

  • Map および Set オブジェクト タイプはコピーできますか?

  • #関数

    オブジェクト タイプはコピーできますか? (通常、関数にはディープ コピーを使用しません)

  • オブジェクトの
  • プロトタイプ

    はコピーできますか?

  • 列挙不可能なプロパティ

    コピーできますか?

  • 循環参照

    コピーできますか? ##################どうやって?あなたが書いた詳細なコピーは十分に完璧ですか?

ディープ コピーの最終実装知りたい人の便宜のために、最終コード バージョンをここに直接示します。もちろん、段階的に理解したい場合は、引き続き記事の残りの部分を参照してください:

function deepClone(target) {
    const map = new WeakMap()
    
    function isObject(target) {
        return (typeof target === 'この記事では、JavaScript のディープ コピーについて詳しく説明します。ect' && target ) || typeof target === 'function'
    }

    function clone(data) {
        if (!isObject(data)) {
            return data
        }
        if ([Date, RegExp].includes(data.constructor)) {
            return new data.constructor(data)
        }
        if (typeof data === 'function') {
            return new Function('return ' + data.toString())()
        }
        const exist = map.get(data)
        if (exist) {
            return exist
        }
        if (data instanceof Map) {
            const result = new Map()
            map.set(data, result)
            data.forEach((val, key) => {
                if (isObject(val)) {
                    result.set(key, clone(val))
                } else {
                    result.set(key, val)
                }
            })
            return result
        }
        if (data instanceof Set) {
            const result = new Set()
            map.set(data, result)
            data.forEach(val => {
                if (isObject(val)) {
                    result.add(clone(val))
                } else {
                    result.add(val)
                }
            })
            return result
        }
        const keys = Reflect.ownKeys(data)
        const allDesc = Object.getOwnPropertyDescriptors(data)
        const result = Object.create(Object.getPrototypeOf(data), allDesc)
        map.set(data, result)
        keys.forEach(key => {
            const val = data[key]
            if (isObject(val)) {
                result[key] = clone(val)
            } else {
                result[key] = val
            }
        })
        return result
    }

    return clone(target)
}

1. JavaScript データ型のコピー原則

まず、JS データ型の図を見てください (

Object

を除き、他はすべて基本型です):

JavaScript では、基本型の値をコピーします。新しい同一のデータを直接コピーします。2 つのデータは相互に排他的で、独立しており、互いに影響しません。参照型の値(オブジェクト型)のコピーとは、オブジェクトの参照(つまり、オブジェクトが配置されているメモリアドレス、つまりオブジェクトへのポインタ)を渡すことであり、これは複数の変数を指すことに相当します。変数の 1 つがそのオブジェクトへの参照を持っている限り、変更されると、他の変数が指すオブジェクトも変更されます (これらの変数は同じオブジェクトを指しているため)。以下に示すように:

2. 深くて浅いコピー
この記事では、JavaScript のディープ コピーについて詳しく説明します。
深くて浅いコピーは、主にオブジェクト タイプと基本の値をターゲットとします。タイプ自体はまったく同じにコピーされます。コピーは 1 つで、暗いコピーと明るいコピーの区別はありません。ここでは、まずテスト用のコピー オブジェクトを提供します。この
この記事では、JavaScript のディープ コピーについて詳しく説明します。この記事では、JavaScript のディープ コピーについて詳しく説明します。 オブジェクトを使用して、作成したディープ コピー関数が完璧かどうかをテストできます:

// 测试的この記事では、JavaScript のディープ コピーについて詳しく説明します。对象
const この記事では、JavaScript のディープ コピーについて詳しく説明します。 = {
    // =========== 1.基础数据类型 ===========
    num: 0, // number
    str: '', // string
    bool: true, // boolean
    unf: undefined, // undefined
    nul: null, // null
    sym: Symbol('sym'), // symbol
    bign: BigInt(1n), // bigint

    // =========== 2.Object类型 ===========
    // 普通对象
    この記事では、JavaScript のディープ コピーについて詳しく説明します。: {
        name: '我是一个对象',
        id: 1
    },
    // 数组
    arr: [0, 1, 2],
    // 函数
    func: function () {
        console.log('我是一个函数')
    },
    // 日期
    date: new Date(0),
    // 正则
    reg: new RegExp('/我是一个正则/ig'),
    // Map
    map: new Map().set('mapKey', 1),
    // Set
    set: new Set().add('set'),
    // =========== 3.其他 ===========
    [Symbol('1')]: 1  // Symbol作为key
};

// 4.添加不可枚举属性
Object.defineProperty(この記事では、JavaScript のディープ コピーについて詳しく説明します。, 'innumerable', {
    enumerable: false,
    value: '不可枚举属性'
});

// 5.设置原型对象
Object.setPrototypeOf(この記事では、JavaScript のディープ コピーについて詳しく説明します。, {
    proto: 'proto'
})

// 6.设置loop成循环引用的属性
この記事では、JavaScript のディープ コピーについて詳しく説明します。.loop = この記事では、JavaScript のディープ コピーについて詳しく説明します。

この記事では、JavaScript のディープ コピーについて詳しく説明します。 オブジェクトChrome の結果にあります:

##2.1 浅いコピー

浅いコピー

: 受け入れる新しいオブジェクトを作成します再コピーまたは参照するオブジェクト値。オブジェクト属性が基本データ型の場合は、基本型の値が新しいオブジェクトにコピーされますが、属性が参照データ型の場合は、メモリ内のアドレスがコピーされます。オブジェクトの 1 つがポイントするアドレスを変更すると、そのアドレスが変更されます。記憶によれば、オブジェクトは間違いなく別のオブジェクトに影響を与えます。 この記事では、JavaScript のディープ コピーについて詳しく説明します。

まず、いくつかの浅いコピー メソッドを見てみましょう (詳細については、対応するメソッドへのハイパーリンクをクリックしてください):

メソッドメソッドを使用する

注意事項

Object.assign(target, .. .sources)説明: 1 つ以上のソース オブジェクトからターゲット オブジェクトにすべての列挙可能なプロパティの値を割り当てるために使用されます。ターゲットオブジェクトを返します。 1. オブジェクトの継承されたプロパティはコピーされません; 2. オブジェクトの非列挙プロパティはコピーされません; 3. シンボル タイプのプロパティはコピーできます。 let この記事では、JavaScript のディープ コピーについて詳しく説明します。Clone = { ...この記事では、JavaScript のディープ コピーについて詳しく説明します。 };Object.assign () ほぼ同じですが、属性がすべて基本型の値である場合、スプレッド演算子を使用して浅いコピーを実行する方が便利です。 const new_array = old_array.concat(value1[, value2[, ...[, valueN] ]])Array.prototype.slice() 配列のコピー浅いコピー、基本型値の配列に適しています

这里只列举了常用的几种方式,除此之外当然还有其他更多的方式。注意,我们直接使用=赋值不是浅拷贝,因为它是直接指向同一个对象了,并没有返回一个新对象。

手动实现一个浅拷贝:

function shallowClone(target) {
    if (typeof target === 'この記事では、JavaScript のディープ コピーについて詳しく説明します。ect' && target !== null) {
        const cloneTarget = Array.isArray(target) ? [] : {};
        for (let prop in target) {
            if (target.hasOwnProperty(prop)) {
                cloneTarget[prop] = target[prop];
            }
        }
        return cloneTarget;
    } else {
        return target;
    }
}


// 测试
const shallowCloneObj = shallowClone(この記事では、JavaScript のディープ コピーについて詳しく説明します。)

shallowCloneObj === この記事では、JavaScript のディープ コピーについて詳しく説明します。  // false,返回的是一个新对象
shallowCloneObj.arr === この記事では、JavaScript のディープ コピーについて詳しく説明します。.arr  // true,对于对象类型只拷贝了引用

从上面这段代码可以看出,利用类型判断(查看typeof),针对引用类型的对象进行 for 循环遍历对象属性赋值给目标对象的属性(for...in语句以任意顺序遍历一个对象的除Symbol以外的可枚举属性,包含原型上的属性。查看for…in),基本就可以手工实现一个浅拷贝的代码了。

2.2 深拷贝

深拷贝:创建一个新的对象,将一个对象从内存中完整地拷贝出来一份给该新对象,并从堆内存中开辟一个全新的空间存放新对象,且新对象的修改并不会改变原对象,二者实现真正的分离。

看看现存的一些深拷贝的方法:

方法1:JSON.stringify()

JSON.stringfy() 其实就是将一个 JavaScript 对象或值转换为 JSON 字符串,最后再用 JSON.parse() 的方法将JSON 字符串生成一个新的对象。(点这了解:JSON.stringfy()、JSON.parse())

使用如下:

function deepClone(target) {
    if (typeof target === 'この記事では、JavaScript のディープ コピーについて詳しく説明します。ect' && target !== null) {
        return JSON.parse(JSON.stringify(target));
    } else {
        return target;
    }
}

// 开头的测试この記事では、JavaScript のディープ コピーについて詳しく説明します。存在BigInt类型、循环引用,JSON.stringfy()执行会报错,所以除去这两个条件进行测试
const clonedObj = deepClone(この記事では、JavaScript のディープ コピーについて詳しく説明します。)

// 测试
clonedObj === この記事では、JavaScript のディープ コピーについて詳しく説明します。  // false,返回的是一个新对象
clonedObj.arr === この記事では、JavaScript のディープ コピーについて詳しく説明します。.arr  // false,说明拷贝的不是引用

浏览器执行结果:

この記事では、JavaScript のディープ コピーについて詳しく説明します。
从以上结果我们可知JSON.stringfy() 存在以下一些问题:

  • 执行会报错:存在BigInt类型、循环引用。

  • 拷贝Date引用类型会变成字符串。

  • 键值会消失:对象的值中为FunctionUndefinedSymbol 这几种类型,。

  • 键值变成空对象:对象的值中为MapSetRegExp这几种类型。

  • 无法拷贝:不可枚举属性、对象的原型链。

  • 补充:其他更详细的内容请查看官方文档:JSON.stringify()

由于以上种种限制条件,JSON.stringfy() 方式仅限于深拷贝一些普通的对象,对于更复杂的数据类型,我们需要另寻他路。

方法2:递归基础版深拷贝

手动递归实现深拷贝,我们只需要完成以下2点即可:

  • 对于基础类型,我们只需要简单地赋值即可(使用=)。

  • 对于引用类型,我们需要创建新的对象,并通过遍历键来赋值对应的值,这个过程中如果遇到 Object 类型还需要再次进行遍历。

function deepClone(target) {
    if (typeof target === 'この記事では、JavaScript のディープ コピーについて詳しく説明します。ect' && target) {
        let cloneObj = {}
        for (const key in target) { // 遍历
            const val = target[key]
            if (typeof val === 'この記事では、JavaScript のディープ コピーについて詳しく説明します。ect' && val) {
                cloneObj[key] = deepClone(val) // 是对象就再次调用该函数递归
            } else {
                cloneObj[key] = val // 基本类型的话直接复制值
            }
        }
        return cloneObj
    } else {
        return target;
    }
}

// 开头的测试この記事では、JavaScript のディープ コピーについて詳しく説明します。存在循环引用,除去这个条件进行测试
const clonedObj = deepClone(この記事では、JavaScript のディープ コピーについて詳しく説明します。)

// 测试
clonedObj === この記事では、JavaScript のディープ コピーについて詳しく説明します。  // false,返回的是一个新对象
clonedObj.arr === この記事では、JavaScript のディープ コピーについて詳しく説明します。.arr  // false,说明拷贝的不是引用

浏览器执行结果:

この記事では、JavaScript のディープ コピーについて詳しく説明します。
该基础版本存在许多问题:

  • 不能处理循环引用。

  • 只考虑了Object对象,而Array对象、Date对象、RegExp对象、Map对象、Set对象都变成了Object对象,且值也不正确。

  • 丢失了属性名为Symbol类型的属性。

  • 丢失了不可枚举的属性。

  • 原型上的属性也被添加到拷贝的对象中了。

如果存在循环引用的话,以上代码会导致无限递归,从而使得堆栈溢出。如下例子:

const a = {}
const b = {}
a.b = b
b.a = a
deepClone(a)

对象 a 的键 b 指向对象 b,对象 b 的键 a 指向对象 a,查看a对象,可以看到是无限循环的:
この記事では、JavaScript のディープ コピーについて詳しく説明します。
对对象a执行深拷贝,会出现死循环,从而耗尽内存,进而报错:堆栈溢出
この記事では、JavaScript のディープ コピーについて詳しく説明します。
如何避免这种情况呢?一种简单的方式就是把已添加的对象记录下来,这样下次碰到相同的对象引用时,直接指向记录中的对象即可。要实现这个记录功能,我们可以借助 ES6 推出的 WeakMap 对象,该对象是一组键/值对的集合,其中的键是弱引用的。其键必须是对象,而值可以是任意的。(WeakMap相关见这:WeakMap)

针对以上基础版深拷贝存在的缺陷,我们进一步去完善,实现一个完美的深拷贝

方法3:递归この記事では、JavaScript のディープ コピーについて詳しく説明します。

对于基础版深拷贝存在的问题,我们一一改进:

##Object.assign()
構文を展開します


欠陥と
Array.prototype.concat() 配列のコピー #浅いコピー、基本的な型値の配列に適しています
arr.slice([begin[, end]])
存在的问题 改进方案
1. 不能处理循环引用 使用 WeakMap 作为一个Hash表来进行查询
2. 只考虑了Object对象 当参数为 DateRegExpFunctionMapSet,则直接生成一个新的实例返回
3. 属性名为Symbol的属性
4. 丢失了不可枚举的属性
针对能够遍历对象的不可枚举属性以及 Symbol 类型,我们可以使用 Reflect.ownKeys()
Reflect.ownKeys(この記事では、JavaScript のディープ コピーについて詳しく説明します。)相当于[...Object.getOwnPropertyNames(この記事では、JavaScript のディープ コピーについて詳しく説明します。), ...Object.getOwnPropertySymbols(この記事では、JavaScript のディープ コピーについて詳しく説明します。)]
4. 原型上的属性 Object.getOwnPropertyDescriptors()设置属性描述对象,以及Object.create()方式继承原型链

代码实现:

function deepClone(target) {
    // WeakMap作为记录对象Hash表(用于防止循环引用)
    const map = new WeakMap()

    // 判断是否为この記事では、JavaScript のディープ コピーについて詳しく説明します。ect类型的辅助函数,减少重复代码
    function isObject(target) {
        return (typeof target === 'この記事では、JavaScript のディープ コピーについて詳しく説明します。ect' && target ) || typeof target === 'function'
    }

    function clone(data) {

        // 基础类型直接返回值
        if (!isObject(data)) {
            return data
        }

        // 日期或者正则对象则直接构造一个新的对象返回
        if ([Date, RegExp].includes(data.constructor)) {
            return new data.constructor(data)
        }

        // 处理函数对象
        if (typeof data === 'function') {
            return new Function('return ' + data.toString())()
        }

        // 如果该对象已存在,则直接返回该对象
        const exist = map.get(data)
        if (exist) {
            return exist
        }

        // 处理Map对象
        if (data instanceof Map) {
            const result = new Map()
            map.set(data, result)
            data.forEach((val, key) => {
                // 注意:map中的值为この記事では、JavaScript のディープ コピーについて詳しく説明します。ect的话也得深拷贝
                if (isObject(val)) {
                    result.set(key, clone(val))
                } else {
                    result.set(key, val)
                }
            })
            return result
        }

        // 处理Set对象
        if (data instanceof Set) {
            const result = new Set()
            map.set(data, result)
            data.forEach(val => {
                // 注意:set中的值为この記事では、JavaScript のディープ コピーについて詳しく説明します。ect的话也得深拷贝
                if (isObject(val)) {
                    result.add(clone(val))
                } else {
                    result.add(val)
                }
            })
            return result
        }

        // 收集键名(考虑了以Symbol作为key以及不可枚举的属性)
        const keys = Reflect.ownKeys(data)
        // 利用 Object 的 getOwnPropertyDescriptors 方法可以获得对象的所有属性以及对应的属性描述
        const allDesc = Object.getOwnPropertyDescriptors(data)
        // 结合 Object 的 create 方法创建一个新对象,并继承传入原对象的原型链, 这里得到的result是对data的浅拷贝
        const result = Object.create(Object.getPrototypeOf(data), allDesc)

        // 新对象加入到map中,进行记录
        map.set(data, result)

        // Object.create()是浅拷贝,所以要判断并递归执行深拷贝
        keys.forEach(key => {
            const val = data[key]
            if (isObject(val)) {
                // 属性值为 对象类型 或 函数对象 的话也需要进行深拷贝
                result[key] = clone(val)
            } else {
                result[key] = val
            }
        })
        return result
    }

    return clone(target)
}



// 测试
const clonedObj = deepClone(この記事では、JavaScript のディープ コピーについて詳しく説明します。)
clonedObj === この記事では、JavaScript のディープ コピーについて詳しく説明します。  // false,返回的是一个新对象
clonedObj.arr === この記事では、JavaScript のディープ コピーについて詳しく説明します。.arr  // false,说明拷贝的不是引用
clonedObj.func === この記事では、JavaScript のディープ コピーについて詳しく説明します。.func  // false,说明function也复制了一份
clonedObj.proto  // proto,可以取到原型的属性

详细的说明见代码中的注释,更多测试希望大家自己动手尝试验证一下以加深印象。

在遍历 Object 类型数据时,我们需要把 Symbol 类型的键名也考虑进来,所以不能通过 Object.keys 获取键名或 for...in 方式遍历,而是通过Reflect.ownKeys()获取所有自身的键名(getOwnPropertyNamesgetOwnPropertySymbols 函数将键名组合成数组也行:[...Object.getOwnPropertyNames(この記事では、JavaScript のディープ コピーについて詳しく説明します。), ...Object.getOwnPropertySymbols(この記事では、JavaScript のディープ コピーについて詳しく説明します。)]),然后再遍历递归,最终实现拷贝。

浏览器执行结果:
この記事では、JavaScript のディープ コピーについて詳しく説明します。
可以发现我们的cloneObj对象和原来的この記事では、JavaScript のディープ コピーについて詳しく説明します。对象一模一样,并且修改cloneObj对象的各个属性都不会对この記事では、JavaScript のディープ コピーについて詳しく説明します。对象造成影响。其他的大家再多尝试体会哦!

【相关推荐:javascript视频教程编程视频

以上がこの記事では、JavaScript のディープ コピーについて詳しく説明します。の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明
この記事はcsdnで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。
Python vs. JavaScript:学習曲線と使いやすさPython vs. JavaScript:学習曲線と使いやすさApr 16, 2025 am 12:12 AM

Pythonは、スムーズな学習曲線と簡潔な構文を備えた初心者により適しています。 JavaScriptは、急な学習曲線と柔軟な構文を備えたフロントエンド開発に適しています。 1。Python構文は直感的で、データサイエンスやバックエンド開発に適しています。 2。JavaScriptは柔軟で、フロントエンドおよびサーバー側のプログラミングで広く使用されています。

Python vs. JavaScript:コミュニティ、ライブラリ、リソースPython vs. JavaScript:コミュニティ、ライブラリ、リソースApr 15, 2025 am 12:16 AM

PythonとJavaScriptには、コミュニティ、ライブラリ、リソースの観点から、独自の利点と短所があります。 1)Pythonコミュニティはフレンドリーで初心者に適していますが、フロントエンドの開発リソースはJavaScriptほど豊富ではありません。 2)Pythonはデータサイエンスおよび機械学習ライブラリで強力ですが、JavaScriptはフロントエンド開発ライブラリとフレームワークで優れています。 3)どちらも豊富な学習リソースを持っていますが、Pythonは公式文書から始めるのに適していますが、JavaScriptはMDNWebDocsにより優れています。選択は、プロジェクトのニーズと個人的な関心に基づいている必要があります。

C/CからJavaScriptへ:すべてがどのように機能するかC/CからJavaScriptへ:すべてがどのように機能するかApr 14, 2025 am 12:05 AM

C/CからJavaScriptへのシフトには、動的なタイピング、ゴミ収集、非同期プログラミングへの適応が必要です。 1)C/Cは、手動メモリ管理を必要とする静的に型付けられた言語であり、JavaScriptは動的に型付けされ、ごみ収集が自動的に処理されます。 2)C/Cはマシンコードにコンパイルする必要がありますが、JavaScriptは解釈言語です。 3)JavaScriptは、閉鎖、プロトタイプチェーン、約束などの概念を導入します。これにより、柔軟性と非同期プログラミング機能が向上します。

JavaScriptエンジン:実装の比較JavaScriptエンジン:実装の比較Apr 13, 2025 am 12:05 AM

さまざまなJavaScriptエンジンは、各エンジンの実装原則と最適化戦略が異なるため、JavaScriptコードを解析および実行するときに異なる効果をもたらします。 1。語彙分析:ソースコードを語彙ユニットに変換します。 2。文法分析:抽象的な構文ツリーを生成します。 3。最適化とコンパイル:JITコンパイラを介してマシンコードを生成します。 4。実行:マシンコードを実行します。 V8エンジンはインスタントコンピレーションと非表示クラスを通じて最適化され、Spidermonkeyはタイプ推論システムを使用して、同じコードで異なるパフォーマンスパフォーマンスをもたらします。

ブラウザを超えて:現実世界のJavaScriptブラウザを超えて:現実世界のJavaScriptApr 12, 2025 am 12:06 AM

現実世界におけるJavaScriptのアプリケーションには、サーバー側のプログラミング、モバイルアプリケーション開発、モノのインターネット制御が含まれます。 2。モバイルアプリケーションの開発は、ReactNativeを通じて実行され、クロスプラットフォームの展開をサポートします。 3.ハードウェアの相互作用に適したJohnny-Fiveライブラリを介したIoTデバイス制御に使用されます。

next.jsを使用してマルチテナントSaaSアプリケーションを構築する(バックエンド統合)next.jsを使用してマルチテナントSaaSアプリケーションを構築する(バックエンド統合)Apr 11, 2025 am 08:23 AM

私はあなたの日常的な技術ツールを使用して機能的なマルチテナントSaaSアプリケーション(EDTECHアプリ)を作成しましたが、あなたは同じことをすることができます。 まず、マルチテナントSaaSアプリケーションとは何ですか? マルチテナントSaaSアプリケーションを使用すると、Singの複数の顧客にサービスを提供できます

next.jsを使用してマルチテナントSaaSアプリケーションを構築する方法(フロントエンド統合)next.jsを使用してマルチテナントSaaSアプリケーションを構築する方法(フロントエンド統合)Apr 11, 2025 am 08:22 AM

この記事では、許可によって保護されたバックエンドとのフロントエンド統合を示し、next.jsを使用して機能的なedtech SaaSアプリケーションを構築します。 FrontEndはユーザーのアクセス許可を取得してUIの可視性を制御し、APIリクエストがロールベースに付着することを保証します

JavaScript:Web言語の汎用性の調査JavaScript:Web言語の汎用性の調査Apr 11, 2025 am 12:01 AM

JavaScriptは、現代のWeb開発のコア言語であり、その多様性と柔軟性に広く使用されています。 1)フロントエンド開発:DOM操作と最新のフレームワーク(React、Vue.JS、Angularなど)を通じて、動的なWebページとシングルページアプリケーションを構築します。 2)サーバー側の開発:node.jsは、非ブロッキングI/Oモデルを使用して、高い並行性とリアルタイムアプリケーションを処理します。 3)モバイルおよびデスクトップアプリケーション開発:クロスプラットフォーム開発は、反応および電子を通じて実現され、開発効率を向上させます。

See all articles

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

VSCode Windows 64 ビットのダウンロード

VSCode Windows 64 ビットのダウンロード

Microsoft によって発売された無料で強力な IDE エディター

DVWA

DVWA

Damn Vulnerable Web App (DVWA) は、非常に脆弱な PHP/MySQL Web アプリケーションです。その主な目的は、セキュリティ専門家が法的環境でスキルとツールをテストするのに役立ち、Web 開発者が Web アプリケーションを保護するプロセスをより深く理解できるようにし、教師/生徒が教室環境で Web アプリケーションを教え/学習できるようにすることです。安全。 DVWA の目標は、シンプルでわかりやすいインターフェイスを通じて、さまざまな難易度で最も一般的な Web 脆弱性のいくつかを実践することです。このソフトウェアは、

SublimeText3 Linux 新バージョン

SublimeText3 Linux 新バージョン

SublimeText3 Linux 最新バージョン

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

MantisBT

MantisBT

Mantis は、製品の欠陥追跡を支援するために設計された、導入が簡単な Web ベースの欠陥追跡ツールです。 PHP、MySQL、Web サーバーが必要です。デモおよびホスティング サービスをチェックしてください。