js高级技巧_JavaScript高级程序

js高级技巧_JavaScript高级程序下述内容主要讲述了《JavaScript高级程序设计(第3版)》第22章关于“高级技巧”。一、高级函数函数是第一等公民,所有函数都是对象。1.安全的类型检测JavaScript内置的类型检测机制并非完全可靠。varisArray=valueinstanceofArray;以上代码要返回true,value必须是一个数组,而且还必须与Array构造函数在同个全局作用域中。(Array是w

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺

下述内容主要讲述了《JavaScript高级程序设计(第3版)》第22章关于“高级技巧”。

一、高级函数

函数是第一等公民,所有函数都是对象。

1. 安全的类型检测

JavaScript内置的类型检测机制并非完全可靠。

var isArray = value instanceof Array;

以上代码要返回true,value必须是一个数组,而且还必须与Array构造函数在同个全局作用域中。(Array是window的属性)如果value是在另外一个iframe中定义的数组,上述代码则返回false。
注意:BOM的核心对象时window,它表示浏览器的一个实例。在浏览器中,window对象有双重角色,它既是通过JavaScript访问浏览器窗口的一个接口,又是ECMAScript规定的global对象。
解决上述问题:
Object原生的toString()方法,都会返回一个[object NativeConstructorName]格式的字符串。

function isArray(value) { 
   
    return Array.isArray(value) || Object.prototype.toString.call(value) == "[object Array]"; 
}

function isType(type) { 
   
    return function(obj) { 
   
        return Object.prototype.toString.call(obj) == "[object " + type + "]"
    }
}
var isObject = isType("Object")
var isArray = Array.isArray || isType("Array")

注意:Object.prototype.toString()本身可能被修改!

2. 作用域安全的构造函数

function Person(name, age) { 
   
    this.name = name;
    this.age = age;
}

当使用new调用时,构造函数内用到的this对象会指向新创建的对象实例。

var p1 = new Person("lg", 26);
console.log(p1.name, p1.age);       // lg 26

到不使用new调用时,由于this是在运行时绑定的,直接调用Person(),this会映射到全局对象window上,导致错误对象属性的意外增加。

var p2 = Person("camile", 26);
console.log(p2.name, p2.age);       // TypeError: Cannot read prototype 'name'
console.log(window.name, age);      // camile 26

注意:由于window的name属性用于识别链接目标和iframe的,上述覆盖可能会导致严重的问题。

解决上述问题:作用域安全构造函数

function Person(name, age) { 
   
    if(this instanceof Person) {
        this.name = name;
        this.age = age;
    } else {
        return new Person(name, age);
    }
}

var p3 = Person("camile", 26);      // 这里没有使用new操作符
console.log(p3.name, p3.age);       // camile 26

通过上述模式,意味着锁定了可以调用构造函数的环境。如果使用构造函数窃取模式继承且不使用原型链,会破坏整个继承

function Polygon(sides) { 
   
    if(this instanceof Polygon) {
        this.sides = sides;
        this.getArea = function() { 
   
            return 0;
        }
    }else {
        return new Polygon(sides);
    }
}

function Rectangle(width, height) { 
   
    Polygon.call(this, 4);
    this.width = width;
    this.height = height;
    this.getArea = function() { 
   
        return this.width * this.height;
    }
}

var rect = new Rectangle(2, 4);
console.log(rect.getArea());    // 8
console.log(rect.sides);    // undefined 

Polygon.call(this, 4)用于Polygon构造函数是作用域安全的,this并非Polygon的实例,所以会创建并返回一个新的Polygon对象,并没有实际作用,this得不到增长,所以Rectangle实例中不会有sides属性。

解决上述问题:使用原型模式或者寄生模式
方式一:原型模式

Rectangle.prototype = new Polygon();
var rect = new Rectangle(2, 4);
console.log(rect.getArea());    // 8
console.log(rect.sides);    // 4

方式二:寄生模式

function Rectangle(width, height) { 
   
    var r = new Polygon(4); 
    r.width = width;
    r.height = height;
    r.getArea = function() { 
   
        return r.width * r.height;
    }
    return r;
}

var rect = new Rectangle(2, 4);
console.log(rect.getArea());    // 8
console.log(rect.sides);    // 4

注意
构造函数内部创建的var r = new Polygon(4)与外部创建没有什么不同。不能依赖instanceof来确定对象类型。

rect instanceof Rectangle;  // false
rect instanceof Polygon;    // true

由于存在上述问题,建议在可以使用其他模式的情况下,不要使用这种模式。

3. 惰性载入函数

可以将任和代码分支推迟到第一次调用函数的时候。
因浏览器之间行为差异,多数JavaScript代码包含大量的if语句。
例如,创建兼容性的XMLHttpRequest对象【Ajax与Comet

/* 兼容IE早期版本 */
function createXHR(){ 
   
    if (typeof XMLHttpRequest != "undefined"){
        return new XMLHttpRequest();
    } else if (typeof ActiveXObject != "undefined"){    // 适用于IE7之前的版本
        if (typeof arguments.callee.activeXString != "string"){
            var versions = ["MSXML2.XMLHttp.6.0", "MSXML2.XMLHttp.3.0",
                            "MSXML2.XMLHttp"],
                i, len;

            for (i=0,len=versions.length; i < len; i++){
                try {
                    new ActiveXObject(versions[i]);
                    arguments.callee.activeXString = versions[i];
                    break;
                } catch (ex){
                    //skip
                }
            }
        }

        return new ActiveXObject(arguments.callee.activeXString);
    } else {  // XHR对象和ActiveX对象都不存在,则抛出错误 
        throw new Error("No XHR object available.");
    }
}

如果浏览器中支持内置XHR对象,每次if判断测试就显得多余了!!!
通过惰性载入的技术可以很好的解决上述问题。
方式一:在函数被调用时再处理函数

function createXHR(){ 
   
    if (typeof XMLHttpRequest != "undefined"){
        createXHR = function(){ 
   
            return new XMLHttpRequest();
        };
    } else if (typeof ActiveXObject != "undefined"){
        createXHR = function(){ 
                       
            if (typeof arguments.callee.activeXString != "string"){
                var versions = ["MSXML2.XMLHttp.6.0", "MSXML2.XMLHttp.3.0",
                                "MSXML2.XMLHttp"],
                    i, len;

                for (i=0,len=versions.length; i < len; i++){
                    try {
                        new ActiveXObject(versions[i]);
                        arguments.callee.activeXString = versions[i];
                    } catch (ex){
                        //skip
                    }
                }
            }
            return new ActiveXObject(arguments.callee.activeXString);
        };
    } else {
        createXHR = function(){ 
   
            throw new Error("No XHR object available.");
        };
    }
    // 调用上述新函数
    return createXHR();
}

方式二:在声明函数时就指定适当的函数

// 自执行,在createXHR声明时,就为其指定了相关创建方法。
var createXHR = (function(){ 
   
    if (typeof XMLHttpRequest != "undefined"){
        return function(){ 
   
            return new XMLHttpRequest();
        };
    } else if (typeof ActiveXObject != "undefined"){
        return function(){ 
                       
            if (typeof arguments.callee.activeXString != "string"){
                var versions = ["MSXML2.XMLHttp.6.0", "MSXML2.XMLHttp.3.0",
                                "MSXML2.XMLHttp"],
                    i, len;

                for (i=0,len=versions.length; i < len; i++){
                    try {
                        new ActiveXObject(versions[i]);
                        arguments.callee.activeXString = versions[i];
                        break;
                    } catch (ex){
                        //skip
                    }
                }
            }

            return new ActiveXObject(arguments.callee.activeXString);
        };
    } else {
        return function(){ 
   
            throw new Error("No XHR object available.");
        };
    }
})();

补充
1. 惰性单例

var getSingle = function(fn) { 
   
    var result;
    return function() { 
   
        return result || (result = fn.apply(this, arguments));
    };
};
// 测试
function testSingle(){ 
   }
getSingle(testSingle)() === getSingle(testSingle)();    // true

2. 系统中提供的页面刷新【回调函数不支持参数】

var refreshPage = (function () { 
   
    var fun;
    function register(callback) { 
   
        fun = callback;
    }
    return function (callback) { 
   
        callback && typeof callback === 'function' ? register(callback) : fun();
    }
})();

// 改写
var refreshPage = (function() { 
   
    var fn;
    return function(callback) { 
   
        callback && typeof callback === 'function' ? fn = callback : fn(); 
    }
})();

4. 函数绑定

函数绑定要创建一个函数,可以在特定的this环境中以指定参数调用另一个函数。

var handler = {
    message: "Event handled",
    handleClick: function(event) { 
   
        console.log(this.message);
    }
};

document.getElementById("btn").addEventListener("click", handler.handleClick);      // undefined
问题在于没有保存handleClick()的环境,this被绑定到了当前DOM按钮上。

// 闭包修正
document.getElementById("btn").addEventListener("click", function() { 
   
    handler.handleClick(event);
});
// 自定义bind方法
function bind(fn, context) { 
   
    return function() { 
   
        return fn.apply(context, arguments);
    };
}
document.getElementById("btn").addEventListener("click", bind(handler.handleClick, handler));
// ES5新增bind方法 Function.prototype.bind
document.getElementById("btn").addEventListener("click", handler.handleClick.bind(handler));

5. 函数柯里化

用于创建已经设置好了一个或多个参数的函数。
其基本方法和函数绑定是一样的:使用一个闭包返回一个函数。
二者区别在于:当函数被调用时,返回的函数还需设置一些传入的参数。

function curry(fn){ 
   
    // 获取参数,并转化为数组(第一个参数为柯里化的函数)
    var args = Array.prototype.slice.call(arguments, 1);
    return function(){ 
   
        // 获取参数,并转化为数组
        var innerArgs = Array.prototype.slice.call(arguments),
            // 所有参数集(最终,有效参数受限于fn)
            finalArgs = args.concat(innerArgs);
        return fn.apply(null, finalArgs);
    };
}

function add(num1, num2){ 
   
    return num1 + num2;
}

var curriedAdd = curry(add, 5);
console.log(curriedAdd(3));   //8

var curriedAdd2 = curry(add, 5, 12);
console.log(curriedAdd2());   //17

var curriedAdd3 = curry(add, 5, 12);
console.log(curriedAdd3(1));   //17
/* 增强版bind */
function bind(fn, context){ 
   
    var args = Array.prototype.slice.call(arguments, 2);
    return function(){ 
   
        var innerArgs = Array.prototype.slice.call(arguments),
            finalArgs = args.concat(innerArgs);
        return fn.apply(context, finalArgs);
    };
}

注意:和上述“函数绑定”中的“自定义bind方法”区分

function enhanchBind(fn, context){ 
   
    var args = Array.prototype.slice.call(arguments, 2);
    return function(){ 
   
        var innerArgs = Array.prototype.slice.call(arguments),
            finalArgs = args.concat(innerArgs);
        return fn.apply(context, finalArgs);
    };
}
document.getElementById("btn").addEventListener("click", enhanchBind(handler.handleClick, handler, event, "函数柯里化"));

二、防篡改对象

一旦把对象定义为防篡改,就无法撤销了。

preventExtensions –> seal –> freeze
isExtensible –> isSealed –> isFrozen

1. 不可扩展对象

默认情况下,所有对象都是可扩展的。意味着,任何时候都可以向对象中添加属性和方法。

var person = {name: "lg"};
person.age = 26;
Object.preventExtensions(person);
person.address = "sd";
console.log(person); // Object {name: "lg", age: 26} address属性没有成功添加
console.log(Object.isExtensible(person)); // false,不可扩展

2. 密封的对象

密封对象不可扩展,而且已有成员的[[configurable]]特性将被设置为false。意味着,不能删除属性和方法。

var person = {name: "lg"};
Object.seal(person);
person.age = 26;
console.log(person);    // Object {name: "lg"} age属性没有成功添加
console.log(Object.isExtensible(person));   // false,不可扩展
console.log(Object.isSealed(person));   // true,密封的

3. 冻结的对象

冻结对象不可扩展、又是密封的,而且已有成员的[[Writable]]特性将被设置为false。如果定义了[[Set]]函数,访问器属性仍可写。

var person = {
    name: "lg",
    _address: "sd"  // 表示私有
};
Object.defineProperty(person, "address", {   // 访问器属性
    get: function() { 
   
        return this._address;
    },
    set: function(add) { 
   
        this._address = add;
    }
})
Object.freeze(person);
person.age = 26;
console.log(person);    // Object {name: "lg", address: "sd"} age属性没有成功添加
person.name = "ligang";
person.address = "shandong";    // ??????

console.log(Object.isExtensible(person));   // false,不可扩展
console.log(Object.isSealed(person));   // true,密封的
console.log(Object.isFrozen(person));   // true,冻结的

对于JavaScript库的作者而言,冻结对象是很有用的,其很好的防止了意外修改库中核心对象。

4. 总结

这里写图片描述

三、高级定时器

JavaScript运行于单线程的环境中,而定时器仅仅只是计划代码在未来的某个时间执行。执行时机不能保证。
定时器对队列的工作方式是,当特定时间过去后将代码插入。注意,给队列添加代码并不意味着对它立即执行,而是能表示它会尽快执行。设定一个150ms后执行的定时器不代表了150ms代码就立刻执行,它表示代码会在150ms后被加入到队列中。如果,在这个时间点上,队列中没有其他东西,那么这段代码就会被执行,表面看上去好像就在精确指定的时间点上执行了。其他情况下,代码可能明显等待更长时间才执行。

谨记:定时器指定的时间间隔表示何时将定时器的代码添加到队列,而不是何时实际执行代码。

1. 重复的定时器

setInterval(),JavaScript引擎“仅当没有该定时器的任何代码实例时“,才将定时器代码添加到队列。这确保了定时器代码加入到队列中的最小时间间隔为指定间隔。
其会存在两个问题:(1)某些间隔会被跳过;(2)多个定时器的代码执行之间的间隔可能会比预期的小。

假如,某个onclick事件处理程序使用setInterval()设置了一该处理是否个200ms间隔的重复定时器。如果事件处理程序花了300ms多一点的时间完成,同时定时器代码也花了差不多的时间,就会同时出现跳过间隔且连续运行定时器代码的情况。

btn.addEventListener("click", function(){ 
   
    // 300ms时间执行
    setInterval(function(){ 
   
        // 执行需要300ms
    }, 200);
});

JavaScript进程时间线
解释:第一个定时器在205ms处添加到队列中,但是直到过了300ms处才能够执行。当执行这个定时器代码时,在405ms处又给队列添加了另外一个副本。在下一个间隔,即605ms处,第一个定时器代码仍在运行,同时在队列中已经有了一个定时器的实例。结果是,在这个时间点上的定时器代码不会被添加到队列中。结果在5ms处添加的定时器代码结束后,405ms处添加的定时器代码就立即执行。

解决上述问题:链式调用setTimeout()

setTimeout(function(){ 
   
    // 处理中
    setTimeout(arguments.callee, interval)
}, interval);

好处:在前一个定时器代码执行完之前,不会向队列插入新的定时器代码,确保不会有任何缺失的间隔。而且,可以保证在下一次定时器代码执行之前,至少等待指定的间隔,避免了连续的运行。

2. Yielding Processes

运行在浏览器中的JavaScript都被分配了一个确定数量的资源,当页面中存在一个耗时较大的脚本时,会导致浏览器卡死。
此时需要考虑两个问题:(1)该处理是否必须同步完成?(2)数据是否必须按顺序完成?
如果都是“否”,则需要考虑“数组分块”技术。

/** * @array 要处理的项目的数组 * @process 处理项目的函数 * @context 运行函数的环境 */
function chunk(array, process, context) { 
   
    setTimeout(function(){ 
   
        var item = array.shift();
        process.call(context, item);
        if(array.length > 0) {
            setTimeout(arguments.callee, 100);
        }
    }, 100);
}

var data = [12,123,1234,453,436,23,23,5,4123,45,346,5634,2234,345,342];
function printValue(item){ 
   
    var div = document.getElementById("myDiv");
    div.innerHTML += item + "<br>";        
}

chunk(data, printValue); // 函数在全局中,所以无需传入执行环境
console.log(data);       // []

注意:传递给chunk()的数组在处理数据时,数组中的条目也在改变。如果想保持原数组保持不变,应该将数组进行克隆。

var data2 = [1, 2, 3];
chunk(data2.concat(), printValue);
console.log(data2);     // [1, 2, 3]

3. 节流处理

在浏览器中,处理DOM交互需要更多的内存和CUP时间。连续尝试进行过多的DOM相关操作可能会导致浏览器挂起,甚至崩溃。
函数节流背后的基本思想是指:某些代码不可以在没有间断的情况连续重复执行。
目的:只有在执行函数的请求停止了一段时间之后才执行。

/** * @param method 方法 * @param scope 当前函数执行作用域 */
function throttle(method, scope) { 
   
    clearTimeout(method.tId);
    method.tId= setTimeout(function(){ 
   
        method.call(scope);
    }, 100);
}

function resizeDiv(){ 
   
    var div = document.getElementById("myDiv");
    div.style.height = div.offsetWidth + "px";
}

// 节流在resize事件中最常用
window.onresize = function(){ 
   
    throttle(resizeDiv);
};

注意:上述函数是一个debounce,而不是一个throttle。debounce与throttle区别

四、自定义事件

事件是一种叫做观察者的设计模式,是一种创建松散耦合代码的技术。
对象可以发布事件,用来表示在该对象生命周期中某个有趣的时刻到了。然后其他对象可以观察该对象,等待这些有趣的时刻到来并通过运行代码来响应。
观察者模式由两类对象组成:主体和观察者。主体负责发布事件,同时观察者订阅这些事件来观察该主体。
JavaScript设计模式–观察者模式

/* 管理事件的对象 */
function EventTarget(){
    this.handlers = {};    
}

EventTarget.prototype = {
    constructor: EventTarget,
    /** * 添加事件 * @param type 事件类型 * @param handler 事件处理程序 */
    addHandler: function(type, handler){
        if (typeof this.handlers[type] == "undefined"){
            this.handlers[type] = [];
        }

        this.handlers[type].push(handler);
    },
    /** * 触发事件 * @param event 事件对象 */
    fire: function(event){
        if (!event.target){
            event.target = this;
        }
        if (this.handlers[event.type] instanceof Array){
            var handlers = this.handlers[event.type];
            for (var i=0, len=handlers.length; i < len; i++){
                handlers[i](event);
            }
        }            
    },
    /** * 移除事件 * @param type 事件类型 * @param handler 事件处理程序 */
    removeHandler: function(type, handler){
        if (this.handlers[type] instanceof Array){
            var handlers = this.handlers[type];
            for (var i=0, len=handlers.length; i < len; i++){
                if (handlers[i] === handler){
                    break;
                }
            }
            handlers.splice(i, 1);
        }            
    }
};

实例1:

// 事件处理程序
function handleMessage(event){ 
   
    alert("Message received: " + event.message);
}
var target = new EventTarget();
// 添加监听
target.addHandler("message", handleMessage);
// 触发事件
target.fire({ type: "message", message: "Hello world!"});
// 移除监听
target.removeHandler("message", handleMessage);
// 触发事件(无效)
target.fire({ type: "message", message: "Hello world!"});

这里写图片描述
实例2:

function object(o){ 
   
    function F(){ 
   }
    F.prototype = o;
    return new F();
}
// 继承 
function inheritPrototype(subType, superType){ 
   
    var prototype = object(superType.prototype);   //create object
    prototype.constructor = subType;               //augment object
    subType.prototype = prototype;                 //assign object
}

function Person(name, age){ 
   
    EventTarget.call(this);
    this.name = name;
    this.age = age;
}

inheritPrototype(Person,EventTarget);

Person.prototype.say = function(message){ 
   
    this.fire({type: "message", message: message});
};
// 事件处理程序
function handleMessage(event){ 
   
    alert(event.target.name + " says: " + event.message);
}

var person = new Person("Nicholas", 29);
// 监听事件
person.addHandler("message", handleMessage);
// 发布事件
person.say("Hi there.");

这里写图片描述
五、拖放
点击某个对象,并按住鼠标按钮不放,将鼠标移动到另一个区域,然后释放鼠标按钮将对象“放”在这里。
拖放的基本概念:创建一个绝对定位的元素,使其可以用鼠标移动。

<!DOCTYPE html>
<html>
<head>
    <title>Drag and Drop Example</title>
</head>
<body>
    <div id="status"></div>
    <div id="myDiv1" class="draggable" style="top:100px;left:0px;background:red;width:100px;height:100px;position:absolute"></div>
    <div id="myDiv2" class="draggable" style="background:blue;width:100px;height:100px;position:absolute;top:100px;left:100px"></div>
    <script type="text/javascript"> var DragDrop = function(){ 
     // EventTarget为上述实例中对象 // 继承EventTarget,具有事件功能 var dragdrop = new EventTarget(), dragging = null, diffX = 0, diffY = 0; function handleEvent(event){ 
     //get event and target var target = event.target; //determine the type of event switch(event.type){ case "mousedown": if (target.className.indexOf("draggable") > -1){ dragging = target; // 保存x、y坐标上的差值 diffX = event.clientX - target.offsetLeft; diffY = event.clientY - target.offsetTop; // 发布自定义事件 dragdrop.fire({type:"dragstart", target: dragging, x: event.clientX, y: event.clientY}); } break; case "mousemove": if (dragging !== null){ //assign location dragging.style.left = (event.clientX - diffX) + "px"; dragging.style.top = (event.clientY - diffY) + "px"; // 发布自定义事件 dragdrop.fire({type:"drag", target: dragging, x: event.clientX, y: event.clientY}); } break; case "mouseup": // 发布自定义事件 dragdrop.fire({type:"dragend", target: dragging, x: event.clientX, y: event.clientY}); dragging = null; break; } }; //全局接口 // 可以拖放 dragdrop.enable = function(){ 
     document.addEventListener("mousedown", handleEvent); document.addEventListener("mousemove", handleEvent); document.addEventListener("mouseup", handleEvent); }; // 禁止拖放 dragdrop.disable = function(){ 
     document.removeEventListener("mousedown", handleEvent); document.removeEventListener("mousemove", handleEvent); document.removeEventListener("mouseup", handleEvent); }; return dragdrop; }(); DragDrop.enable(); // 监听(订阅)相关自定义事件  DragDrop.addHandler("dragstart", function(event){ 
     var status = document.getElementById("status"); status.innerHTML = "Started dragging " + event.target.id; }); DragDrop.addHandler("drag", function(event){ 
     var status = document.getElementById("status"); status.innerHTML += "<br>Dragged " + event.target.id + " to (" + event.x + "," + event.y + ")"; }); DragDrop.addHandler("dragend", function(event){ 
     var status = document.getElementById("status"); status.innerHTML += "<br>Dropped " + event.target.id + " at (" + event.x + "," + event.y + ")"; }); </script>
</body>
</html>

这里写图片描述

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/171277.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)
blank

相关推荐

  • python3基础:操作mysql数据库

    python3基础:操作mysql数据库mysql登陆基本操作:登陆:mysql-uroot-h127.0.0.1-P3306-pmysql-uroot-p(本机不用写host)退出mysql:ctrl+z+回车,或者exit端口号默认是3306,但是可以通过安装目录下的配置文件修改。使用流程引用API模块获取与数据库的连接执行sql语句与存储过程关闭数据库连接安装pymysqlpython3与…

  • tikv 安装_tia v16安装步骤

    tikv 安装_tia v16安装步骤exportHostIP=”127.0.0.1″dockerrun-d-p2379:2379-p2380:2380–namepdpingcap/pd\–name=”pd”\–data-dir=”pd”\–client-urls=”http://0.0.0.0:2379″\-…

  • hdu 5685

    hdu 5685

  • BP神经网络的Matlab实现——人工智能算法

    BP神经网络的Matlab实现——人工智能算法这几天在各大媒体上接触到了人工智能机器学习,觉得很有意思,于是开始入门最简单的机器算法——神经网络训练算法(NeuralNetworkTraining);以前一直觉得机器学习很高深,到处是超高等数学、线性代数、数理统计。入坑发现确实是这样!但是呢由项目实例驱动的学习比起为考试不挂科为目的的学习更为高效、实用!在遗传算法、神经网络算法的学习入门之后觉得数学只要用心看没问题的(即使是蒙特卡洛和马尔

  • java怎样解决除法精度_java 除法 精度问题

    java怎样解决除法精度_java 除法 精度问题inta=4;intb=3;floatc=(float)a/b;System.out.print(c);//输出:1如果要的到精确的结果,要用下面的方法inta=4;intb=3;floatc=(float)a/(float)b;System.out.print(c);//输出:1.3333334importjava.text.DecimalFormat;public…

  • onpropertychange & oninput兼容性

    onpropertychange & oninput兼容性onpropertychange:适用IE,谷歌不适用。IE:监听所有属性,也适用js改变value<inputname=”fundName”id=”fundName”type=”hidden”value='<DM:DocumentTagfield=”fundName”/>’onpropertychange=”{ if(”==this.value){ return; } varvtime=document.f1.sys_createtime.value;

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号