代码之家  ›  专栏  ›  技术社区  ›  Enoy

Javascript:重构现有代码以分离关注点,我们如何使用类/原型并从它自己的对象方法调用?

  •  0
  • Enoy  · 技术社区  · 6 年前

    我有一个网页,其中我展示了两个模型,每个模型都使用Threejs放在画布上。

    我想读一个本地文件,解析它,然后让它可以下载。

    我已经做到了,所有这些都是混合的,我的意思是,逻辑既负责显示画布,也负责读取、解析和下载文件。

    我想将文件读取、解析和下载逻辑隔离到另一个类中。目前,我在一个名为InitCanvas的类中提取了画布的显示逻辑。js公司

    代码如下:

    // this class handles the load and the canva for a nrrd
    // Using programming based on prototype: https://javascript.info/class
    // This class should be improved:
    //   - Canvas Width and height
    
    InitCanvas = function (IdDiv, Filename) {
    
    
        this.IdDiv = IdDiv;
        this.Filename = Filename
    }
    
    InitCanvas.prototype = {
    
        constructor: InitCanvas,
    
        init: function () {
    
            this.container = document.getElementById(this.IdDiv);
    
            // this should be changed.
            this.container.innerHeight = 600;
            this.container.innerWidth = 800;
    
            //These statenments should be changed to improve the image position
            this.camera = new THREE.PerspectiveCamera(60, this.container.innerWidth / this.container.innerHeight, 0.01, 1e10);
            this.camera.position.z = 300;
    
            let scene = new THREE.Scene();
            scene.add(this.camera);
    
            // light
    
            let dirLight = new THREE.DirectionalLight(0xffffff);
            dirLight.position.set(200, 200, 1000).normalize();
    
            this.camera.add(dirLight);
            this.camera.add(dirLight.target);
    
    
            // read file
    
            let loader = new THREE.NRRDLoader();
            loader.load(this.Filename, function (volume) {
    
                //z plane
                let sliceZ = volume.extractSlice('z', Math.floor(volume.RASDimensions[2] / 4));
    
                this.container.innerWidth = sliceZ.iLength;
                this.container.innerHeight = sliceZ.jLength;
    
                sliceZ.mesh.material.color.setRGB(0,1,1);
    
    
                console.log('Our slice is: ', sliceZ);
    
                scene.add(sliceZ.mesh);
            }.bind(this));
    
    
            this.scene = scene;
    
            // renderer
    
            this.renderer = new THREE.WebGLRenderer({alpha: true});
            this.renderer.setPixelRatio(this.container.devicePixelRatio);
            this.renderer.setSize(this.container.innerWidth, this.container.innerHeight);
    
            // add canvas in container
            this.container.appendChild(this.renderer.domElement);
    
    
    
    
    
        },
    
        animate: function () {
    
            this.renderer.render(this.scene, this.camera);
        }
    
    }
    

    因此,我们的想法是重构逻辑。js公司:

    if (!Detector.webgl) Detector.addGetWebGLMessage();
    
    // global variables for this scripts
    let OriginalImg,
        SegmentImg;
    
    var mouse = new THREE.Vector2();
    var raycaster = new THREE.Raycaster();
    var mousePressed = false;
    var clickCount = 0;
    var allText;
    
    
    init();
    animate();
    readTextFile("columna01-es-latin1.txt");
    
    
    // initilize the page
    function init() {
    
    
        let filename = "models/nrrd/columna01.nrrd"; // change your nrrd file
        let idDiv = 'original';
        OriginalImg = new InitCanvas(idDiv, filename);
        OriginalImg.init();
        console.log(OriginalImg);
    
        filename = "models/nrrd/columnasegmentado01.nrrd"; // change your nrrd file
        idDiv = 'segment';
        SegmentImg = new InitCanvas(idDiv, filename);
        SegmentImg.init();
    }
    
    let originalCanvas = document.getElementById('original');
    originalCanvas.addEventListener('mousedown', onDocumentMouseDown, false);
    originalCanvas.addEventListener('mouseup', onDocumentMouseUp, false);
    
    
    function onDocumentMouseDown(event) {
        mousePressed = true;
    
        clickCount++;
    
        mouse.x = ( ( event.clientX - OriginalImg.renderer.domElement.offsetLeft ) / OriginalImg.renderer.domElement.clientWidth ) * 2 - 1;
        mouse.y = -( ( event.clientY - OriginalImg.renderer.domElement.offsetTop ) / OriginalImg.renderer.domElement.clientHeight ) * 2 + 1
    
        console.log('Mouse x position is: ', mouse.x, 'the click number was: ', clickCount);
        console.log('Mouse Y position is: ', mouse.y);
    
        raycaster.setFromCamera(mouse.clone(), OriginalImg.camera);
        var objects = raycaster.intersectObjects(OriginalImg.scene.children);
    
        console.log(objects);
    }
    
    function onDocumentMouseUp(event) {
        mousePressed = false
    }
    
    
    function animate() {
    
    
        requestAnimationFrame(animate);
        OriginalImg.animate();
        SegmentImg.animate();
    
    
    }
    
    function readTextFile(file) {
        var rawFile = new XMLHttpRequest();
        rawFile.open("GET", file, false);
        rawFile.onreadystatechange = function () {
            if (rawFile.readyState === 4) {
                if (rawFile.status === 200 || rawFile.status == 0) {
                    allText = rawFile.responseText;
                    console.log('The complete text is', allText);
                    let lineArr = intoArray(allText);
                    let firstLineWords = intoWords(lineArr[0]);
                    let secondLineWords = intoWords(lineArr[1]);
    
                    console.log('Our  first line is: ', lineArr[0]);
    
                    let atlas = {};
                    for (let i = 0; i < firstLineWords.length; i++) {
                        console.log(`Our ${i} word in the first line is : ${firstLineWords[i]}`);
                        console.log(`Our ${i} word in the SECOND line is : ${secondLineWords[i]}`);
                        atlas[firstLineWords[i]] = secondLineWords[i];
                    }
                    console.log('The atlas is: ', atlas);
                    let atlasJson = JSON.stringify(atlas);
                    console.log('Atlas as json is: ', atlasJson);
    
                    download(atlasJson, 'atlasJson.txt', 'text/plain');
                }
            }
        };
        rawFile.send(null);
    }
    
    // Function to download data to a file
    function download(text, name, type) {
        var a = document.getElementById("a");
        var file = new Blob([text], {type: type});
        a.href = URL.createObjectURL(file);
        a.download = name;
    }
    
    
    function intoArray(lines) {
        // splitting all text data into array "\n" is splitting data from each new line
        //and saving each new line as each element*
    
        var lineArr = lines.split('\n');
    
        //just to check if it works output lineArr[index] as below
    
    
        return lineArr;
    
    
    }
    
    function intoWords(line) {
    
    
        var wordsArr = line.split('" "');
    
    
        return wordsArr;
    }
    

    要提取readTextFile,请在其自己的类中下载、intoArray、intoWords。

    作为一个名为myFileReader的新类,我尝试了以下方法:

    MyFileReader = function () {
    
    
    
    }
    
    MyFileReader.prototype = {
    
        constructor: MyFileReader,
    
        readTextFile: function (file, intoLines, intoWords) {
    
            var rawFile = new XMLHttpRequest();
            rawFile.open("GET", file, false);
            rawFile.onreadystatechange = function () {
                if (rawFile.readyState === 4) {
                    if (rawFile.status === 200 || rawFile.status == 0) {
                        allText = rawFile.responseText;
                        console.log('The complete text is', allText);
                        let lineArr = this.intoLines(allText);
                        let firstLineWords = this.intoWords(lineArr[0]);
                        let secondLineWords = this.intoWords(lineArr[1]);
    
                        console.log('Our  first line is: ', lineArr[0]);
    
                        let atlas = {};
                        for (let i = 0; i < firstLineWords.length; i++) {
                            console.log(`Our ${i} word in the first line is : ${firstLineWords[i]}`);
                            console.log(`Our ${i} word in the SECOND line is : ${secondLineWords[i]}`);
                            atlas[firstLineWords[i]] = secondLineWords[i];
                        }
                        console.log('The atlas is: ', atlas);
                        let atlasJson = JSON.stringify(atlas);
                        console.log('Atlas as json is: ', atlasJson);
    
                        this.download(atlasJson, 'atlasJson.txt', 'text/plain');
                    }
                }
            };
            rawFile.send(null);
        },
    
        download: function (text, name, type) {
    
            var a = document.getElementById("a");
            var file = new Blob([text], {type: type});
            a.href = URL.createObjectURL(file);
            a.download = name;
        },
        intoLines: function (text) {
            // splitting all text data into array "\n" is splitting data from each new line
            //and saving each new line as each element*
    
            var lineArr = text.split('\n');
    
            //just to check if it works output lineArr[index] as below
    
    
            return lineArr;
    
    
        },
        intoWords: function (lines) {
    
    
            var wordsArr = lines.split('" "');
    
    
            return wordsArr;
    
        },
    
    };
    

    我从逻辑上使用它。js组件:

    myFileReader = new MyFileReader();
    myFileReader.readTextFile("columna01-es-latin1.txt");
    

    问题是:

    1、为什么我们会得到:

    TypeError: this.intoLines is not a function
    

    参考该行:

                let lineArr = this.intoLines(allText);
    

    此外,为了解决此错误,我还尝试从对象传入函数,如下所示:

    思维方式js公司:

    myFileReader = new MyFileReader();
    myFileReader.readTextFile("columna01-es-latin1.txt", myFileReader.intoLines(), myFileReader.intoWords());
    

    在我们班上,是MyFileReader。js,在readtTextFile中,我们放置了:

    let lineArr = intoLines(allText);
    let firstLineWords = intoWords(lineArr[0]);
    let secondLineWords = intoWords(lineArr[1]);
    

    我们的web控制台告诉我们:

    TypeError: text is undefined
    

    我理解文本是未定义的,因为在逻辑上。js我们不提供:

    myFileReader.readTextFile("columna01-es-latin1.txt", myFileReader.intoLines(), myFileReader.intoWords());
    

    然而,我认为我们不能提供它,因为我们实际上是在请求myFileReader读取本地文件中的所有文本,并将其传递给intoLines()方法。

    2、为什么会发生,我们如何解决?

    谢谢你的帮助!

    编辑:

    @Bergi建议后的最终代码是:

    function readTextFile(file) {
    
        var rawFile = new XMLHttpRequest();
        rawFile.open("GET", file, false);
        rawFile.onreadystatechange = function () {
            if (rawFile.readyState === 4) {
                if (rawFile.status === 200 || rawFile.status == 0) {
                    allText = rawFile.responseText;
                    console.log('The complete text is', allText);
                    let lineArr = intoLines(allText);
                    let firstLineWords = intoWords(lineArr[0]);
                    let secondLineWords = intoWords(lineArr[1]);
    
                    console.log('Our  first line is: ', lineArr[0]);
    
                    let atlas = {};
                    for (let i = 0; i < firstLineWords.length; i++) {
                        console.log(`Our ${i} word in the first line is : ${firstLineWords[i]}`);
                        console.log(`Our ${i} word in the SECOND line is : ${secondLineWords[i]}`);
                        atlas[firstLineWords[i]] = secondLineWords[i];
                    }
                    console.log('The atlas is: ', atlas);
                    let atlasJson = JSON.stringify(atlas);
                    console.log('Atlas as json is: ', atlasJson);
    
                    download(atlasJson, 'atlasJson.txt', 'text/plain');
                }
            }
        };
        rawFile.send(null);
    }
    
    function download(text, name, type) {
    
        var a = document.getElementById("a");
        var file = new Blob([text], {type: type});
        a.href = URL.createObjectURL(file);
        a.download = name;
    }
    
    function intoLines(text) {
        // splitting all text data into array "\n" is splitting data from each new line
        //and saving each new line as each element*
    
        var lineArr = text.split('\n');
    
        //just to check if it works output lineArr[index] as below
    
    
        return lineArr;
    
    
    }
    
    function intoWords(lines) {
    
    
        var wordsArr = lines.split('" "');
    
    
        return wordsArr;
    
    }
    

    我还研究了:

    原型:这条线对我帮助很大

    How does JavaScript .prototype work?

    如何将文件下载到本地存储

    JavaScript: Create and save file

    如何从对象中删除属性 How do I remove a property from a JavaScript object?

    1 回复  |  直到 6 年前
        1
  •  1
  •   Bergi    6 年前

    为什么会发生这种情况,我们如何解决它?

    看见 How to access the correct `this` inside a callback?

    作为一个新班级,我尝试了以下内容

    这是你的问题。根本没有理由使用类构造,您不会实例化它并保留对象上的数据。

    是的,将readTextFile、download、intoArray、intoWords提取到自己的模块中,在自己的文件中,这是一个好主意。但是没有理由使用(空!)构造函数和原型,仅使用普通函数就可以了(而且您在访问实例方法时也不会遇到上述问题)。