> 웹 프론트엔드 > JS 튜토리얼 > 보다 안정적이고 읽기 쉬운 JavaScript 코드를 작성하는 방법을 알려주는 예

보다 안정적이고 읽기 쉬운 JavaScript 코드를 작성하는 방법을 알려주는 예

黄舟
풀어 주다: 2017-03-15 14:59:02
원래의
1246명이 탐색했습니다.

누구나 자신만의 프로그래밍 스타일이 있으며, 다른 사람의 프로그래밍 스타일을 느끼는 것은 불가피합니다. 즉, 다른 사람의 코드를 수정하는 것입니다. "다른 사람의 코드를 수정하는 것"은 우리에게 있어서 매우 고통스러운 일입니다. 일부 코드는 읽고 유지하기가 쉽지 않기 때문에 다른 사람이 다른 사람의 코드를 수정하도록 허용하면 결국 변수 를 수정하고 함수 의 호출 타이밍을 조정하는 결과를 가져올 수 있습니다. 다른 사람의 코드를 읽고 명확하게 만드는 데 한 시간 이상 걸립니다. 이 글에서는 위치를 획득하는 "구성 요소"를 재구성하는 방법을 단계별로 안내하여 javascript 코드의 가독성과 안정성을 향상시킵니다.

이 글의 내용은 다음과 같습니다.

  • 자바스크립트 코드를 분리하세요

  • 함수에 의존하면 안 됩니다. 외부 환경에 너무 많은 영향

  • 의미및 재사용

  • 구성 요소는 논리, 동작그냥 캡슐화

  • 나만의 코드 스타일 만들기

자바스크립트 코드 분리

다음 부분 코드 읽기의 어려움을 보여줌/수정된 코드:

(function (window, namespace) {
    var $ = window.jQuery;
    window[namespace] = function (targetId, textId) {
        //一个尝试复用的获取位置的"组件"
        var $target = $('#' + targetId),//按钮
            $text = $('#' + textId);//显示文本
        $target.on('click', function () {
            $text.html('获取中');
            var data = '北京市';//balabala很多逻辑,伪代码,获取得到位置中
            if (data) {
                $text.html(data);
            } else
                $text.html('获取失败');
        });
    }
})(window, 'linkFly');
로그인 후 복사

이 코드 조각은 일시적으로 "구성 요소"를 구성한다는 것을 인정합니다.

위의 코드는 모든 작업을 수행하는 일반적인 방법입니다. 일단 내부 로직이 채워지면 생활이 불가능해집니다. 그리고 수요가 증가하면 예를 들어 위치를 가져와서 반환된 데이터 형식을 처리해야 합니다. 그러면 안으로 들어가서 데이터를 처리하는 코드가 수정됩니다.

로직을 분리하여 다음과 같이 코드를 얻습니다.

(function (window, namespace) {
    var $ = window.jQuery,
        $target,
        $text,
        states= ['获取中', '获取失败'];
    function done(address) {//获取位置成功
        $text.html(address);
    }
    function fail() {
        $text.html(states[1]);
    }
    function checkData(data) {
        //检查位置信息是否正确
        return !!data;
    }
    function loadPosition() {
        var data = '北京市';//获取位置中
        if (checkData(data)) {
            done(data);
        } else
            fail();
    }
    var init = function () {
        $target.on('click', function () {
            $text.html(states[0]);
            loadPosition();
        });
    };
    window[namespace] = function (targetId, textId) {
        $target = $('#' + targetId);
        $text = $('#' + textId);
        initData();
        setData();
    }
})(window, 'linkFly');
로그인 후 복사

함수는 외부 환경에 너무 많이 의존해서는 안 됩니다.

위 코드에서는 전체 구성 요소를 다양한 구성 요소로 함수화할 때(메소드가 아니라 함수에 대해 이야기하고 있다는 점에 유의하세요) 여기서 새로운 문제가 자주 발생합니다. 함수는 제어할 수 없는 변수에 너무 많이 의존합니다.

$target 및 $text 변수는 환경의 전역 변수이며 구성 요소가 초기화될 때 값이 할당됩니다. 컷 코드의 대부분의 작업 방법은 $text, 특히 $text 및 done에 의존합니다. () , failure(), $text와 관련된 구조와 로직이 변경되면 우리 코드는 상당한 변경을 겪게 됩니다.

페이지/DOM과 관련된 것(예: $target 및 $text)은 신뢰할 수 없습니다. 페이지 구조가 변경되면 해당 동작도 크게 변경됩니다. 그리고 기능은 외부 환경에 의존해서는 안 됩니다.

제어할 수 없는 변수에 대해서는 함수와 종속변수의 관계를 풀어서 함수가 자신의 영역의 논리에 더욱 집중하고 순수해질 수 있도록 해야 합니다. 간단히 말하면, 함수가 의존하는 모든 외부 변수는 매개변수를 통해 함수에 전달되어야 합니다.
새 코드는 다음과 같습니다.

(function (window, namespace) {
    var $ = window.jQuery;
    //检查位置信息是否正确
    function checkData(data) {
        return !!data;
    }
    //获取位置中
    function loadPosition(done, fail) {
        var data = '北京市';//获取位置中
        if (checkData(data)) {
            done(data);
        } else
            fail();
    }
    window[namespace] = function (targetId, textId) {
       var  $target = $('#' + targetId),
            $text = $('#' + textId);
        var states = ['获取中', '获取失败'];
        $target.on('click', function () {
            $text.html(states[0]);
            loadPosition(function (address) {//获取位置成功
                $text.html(address);
            }, function () {//获取位置失败
                $text.html(states[1]);
            });
        });
    }
})(window, 'linkFly');
로그인 후 복사

의미화 및 재사용

변수 상태는

배열입니다. 설명하는 동작은 매번 읽기 어렵습니다. 상태 [0]이 보입니다. 코드에서 상태 변수의 값을 항상 기억해야 하기 때문에 우리 모두는 매 순간 원저자를 죽이고 싶은 충동을 느낍니다.

또한, 위 코드의 $text.html은 전형적인 코드 중복이므로, 이번에는 수정된 코드에서 ChangeStateText()의 코드 위치에 주의해 주시기 바랍니다. 상위 환경(즉, 대규모

폐쇄 전체의 환경)으로 승격되었습니다.

(function (window, namespace) {
    var $ = window.jQuery;
    function checkData(data) {
        return !!data;
    }
    function loadPosition(done, fail) {
        var data = '北京市';//获取位置中
        if (checkData(data)) {
            done(data);
        } else
            fail();
    }
    window[namespace] = function (targetId, textId) {
        var $target = $('#' + targetId),
            $text = $('#' + textId),
            changeEnum = { LOADING: '获取中', FAIL: '获取失败' },
            changeStateText = function (text) {
                $text.html(text);
            };
        $target.on('click', function () {
            changeStateText(changeEnum.LOADING);
            loadPosition(function (address) {
                changeStateText(address);
            }, function () {
                changeStateText(changeEnum.FAIL);
            });
        });
    }
})(window, 'linkFly');
로그인 후 복사

의미론에 관해서는 전체 현재 코드의 논리와 의미를 알아야 합니다.

이 전체 구성 요소에서 모든 기능 모듈은 도구와 도구 공급자로 나눌 수 있습니다.

상위 계층 환경(대형 클로저 전체)은 우리 비즈니스에서 도구 역할을 합니다. 그 임무는 위치 논리 획득과 관련된 도구 세트를 창[네임스페이스]에 만드는 것입니다. function 은 도구 제공자의 아이덴티티이며 유일한 입구이며 도구 사용자에게 구성 요소의 전체 비즈니스를 제공하는 역할을 담당합니다.

여기서 $text.html()은 논리적으로 도구에 속하지 않고 도구 사용 후 도구 제공자가 얻은 피드백에 속하므로 ChangeStateText() 함수는 도구 제공자 창[네임스페이스]에 배치됩니다. () .

组件应该关注逻辑,行为只是封装

到此为止,我们分离了函数,并让这个组件拥有了良好的语义。但这时候来了新的需求:当没有获取到位置的时候,需要进行一些其他的操作。这时候会发现,我们需要window[namespace]()上加上新的参数。
当我们加上新的参数之后,又被告知新的需求:当获取位置失败了之后,需要修改一些信息,然后再次尝试获取位置信息。
不过幸好,我们的代码已经把大部分的逻辑抽离到了工具提供者中了,对整个工具的逻辑影响并不大。
同时我们再看看代码就会发现我们的组件除了工具提供者之外,没有方法(依赖在对象上的函数)。也就是说,我们的组件并没有对象。

我见过很多人的代码总是喜欢打造工具提供者,而忽略了工具的本质。迎合上面的增加的需求,那么我们的工具提供者将会变得越来越重,这时候我们应该思考到:是不是应该把工具提供出去?

让我们回到最初的需求——仅仅只是一个获取位置的组件,没错,它的核心业务就是获取位置——它不应该被组件化。它的本质应该是个工具对象,而不应该和页面相关,我们从一开始就不应该关注页面上的变化,让我们重构代码如下:

(function (window, namespace) {
    var Gps = {
        load: function (fone, fail) {
            var data = '北京市';//获取位置伪代码
            this.check(data) ?
                done(data, Gps.state.OK) :
                fail(Gps.state.FAIL);
        },
        check: function (data) {
            return !!data;
        },
        state: { OK: 1, FAIL: 0 }
    };
    window[namespace] = Gps;
})(window, 'Gps');
로그인 후 복사

在这里,我们直接捏死了工具提供者,我们直接将工具提供给外面的工具使用者,让工具使用者直接使用我们的工具,这里的代码无关状态、无关页面。

至此,重构完成。

形成自己风格的代码

之所以讲这个是因为大家都有自己的编程风格。有些人的编程风格就是开篇那种代码的…
我觉得形成自己的编程风格,是建立在良好代码的和结构/语义上的。否则只会让你的代码变得越来越难读,越来越难写。
****
单var和多var
我个人是喜欢单var风格的,不过我觉得代码还是尽可能在使用某一方法/函数使用前进行var,有时候甚至于为了单var而变得丧心病狂:由于我又过分的喜爱函数表达式声明,函数表达式声明并不会在var语句中执行,于是偶尔会出现这种边声明边执行的代码,为了不教坏小朋友就不贴代码了(我不会告诉你们其实是我找不到了)。

对象属性的屏蔽
下面的代码演示了两种对象的构建,后一种通过闭包把内部属性隐藏,同样,两种方法都实现了无new化,我个人…是不喜欢看见很多this的..但还是推荐前者。

(function () {
    //第一种,曝露了_name属性
    var Demo = function () {
        if (!(this instanceof Demo))
            return new Demo();
        this._name = 'linkFly';
    };
    Demo.prototype.getName = function () {
        return this._name;
    }

    //第二种,多一层闭包意味内存消耗更大,但是屏蔽了_name属性
    var Demo = function () {
        var name = 'linkFly';
        return {
            getName: function () {
                return name;
            }
        }
    }
});
로그인 후 복사

巧用变量置顶[hoisting]
巧用函数声明的变量置顶特性意味着处女座心态的你放弃单var,但却可以让你的函数在代码结构上十分清晰,例如下面的代码:

(function () {
    var names = [];
    return function (name) {
        addName(name);
    }
    function addName(name) {
        if (!~names.indexOf(name))//如果存在则不添加
            names.push(name);
        console.log(names);// ["linkFly"]
    }
}())('linkFly');
로그인 후 복사

if和&&
这种代码,在几个群里都见过讨论:

(function () {
    var key = 'linkFly',
        cache = { 'linkFly': 'http://www.cnblogs.com/silin6/' },
        value;
    //&&到底
    key && cache && cache[key] && (value = cache[key]);
    //来个if
    if (key && cache && cache[key])
        value = cache[key];
})();
로그인 후 복사

위 내용은 보다 안정적이고 읽기 쉬운 JavaScript 코드를 작성하는 방법을 알려주는 예의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

원천:php.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿