JS 数据类型转换 方法主要有三种

转换函数、强制类型转换、利用js变量弱类型转换。

1. 转换函数:

js提供了parseInt()和parseFloat()两个转换函数。前者把值转换成整数,后者把值转换成浮点数。只有对String类型调用这些方法,这两个函数才能正确运行;对其他类型返回的都是NaN(Not a Number)。

在判断字符串是否是数字值前,parseInt()和parseFloat()都会仔细分析该字符串。parseInt()方法首先查看位置0处的 字符,判断它是否是个有效数字;如果不是,该方法将返回NaN,不再继续执行其他操作。但如果该字符是有效数字,该方法将查看位置1处的字符,进行同样的 测试。这一过程将持续到发现非有效数字的字符为止,此时parseInt()将把该字符之前的字符串转换成数字。

例如,如果要把字符串 "1234blue "转换成整数,那么parseInt()将返回1234,因为当它检测到字符b时,就会停止检测过程。字符串中包含的数字字面量会被正确转换为数字,因此 字符串 "0xA "会被正确转换为数字10。不过,字符串 "22.5 "将被转换成22,因为对于整数来说,小数点是无效字符。一些示例如下:

parseInt("1234blue");   //returns   1234 
parseInt("0xA");   //returns   10 
parseInt("22.5");   //returns   22 
parseInt("blue");   //returns   NaN

parseInt()方法还有基模式,可以把二进制、八进制、十六进制或其他任何进制的字符串转换成整数。基是由parseInt()方法的第二个参数指定的,所以要解析十六进制的值,需如下调用parseInt()方法: 
parseInt("AF",   16);   //returns   175 
当然,对二进制、八进制,甚至十进制(默认模式),都可以这样调用parseInt()方法: 
parseInt("10",   2);   //returns   2 
parseInt("10",   8);   //returns   8 
parseInt("10",   10);   //returns   10 
如果十进制数包含前导0,那么最好采用基数10,这样才不会意外地得到八进制的值。例如: 
parseInt("010");   //returns   8 
parseInt("010",   8);   //returns   8 
parseInt("010",   10);   //returns   10 
在这段代码中,两行代码都把字符串 "010 "解析成了一个数字。第一行代码把这个字符串看作八进制的值,解析它的方式与第二行代码(声明基数为8)相同。最后一行代码声明基数为10,所以iNum3最后等于10。

parseFloat()方法与parseInt()方法的处理方式相似,从位置0开始查看每个字符,直到找到第一个非有效的字符为止,然后把该字 符之前的字符串转换成数字。不过,对于这个方法来说,第一个出现的小数点是有效字符。如果有两个小数点,第二个小数点将被看作无效的, parseFloat()方法会把这个小数点之前的字符串转换成数字。这意味着字符串 "22.34.5 "将被解析成22.34。 
使用parseFloat()方法的另一不同之处在于,字符串必须以十进制形式表示浮点数,而不能用八进制形式或十六进制形式。该
方法会忽略前导0,所以八进制数0908将被解析为908。对于十六进制数0xA,该方法将返回NaN,因为在浮点数中,x不是有效字符。此外,parseFloat()也没有基模式。

下面是使用parseFloat()方法的示例: 
parseFloat("1234blue");   //returns   1234.0 
parseFloat("0xA");   //returns   NaN 
parseFloat("22.5");   //returns   22.5 
parseFloat("22.34.5");   //returns   22.34 
parseFloat("0908");   //returns   908 
parseFloat("blue");   //returns   NaN

2. 强制类型转换

还可使用强制类型转换(type casting)处理转换值的类型。使用强制类型转换可以访问特定的值,即使它是另一种类型的。
ECMAScript中可用的3种强制类型转换如下: 
Boolean(value)——把给定的值转换成Boolean型; 
Number(value)——把给定的值转换成数字(可以是整数或浮点数); 
String(value)——把给定的值转换成字符串。 
用这三个函数之一转换值,将创建一个新值,存放由原始值直接转换成的值。这会造成意想不到的后果。 
当要转换的值是至少有一个字符的字符串、非0数字或对象(下一节将讨论这一点)时,Boolean()函数将返回true。如果该值是空字符串、数字0、undefined或null,它将返回false。

可以用下面的代码段测试Boolean型的强制类型转换。

Boolean("");   //false   –   empty   string 
Boolean("hi");   //true   –   non-empty   string 
Boolean(100);   //true   –   non-zero   number 
Boolean(null);   //false   -   null 
Boolean(0);   //false   -   zero 
Boolean(new   Object());   //true   –   object

Number()的强制类型转换与parseInt()和parseFloat()方法的处理方式相似,只是它转换的是整个值,而不是部分值。还记 得吗,parseInt()和parseFloat()方法只转换第一个无效字符之前的字符串,因此 "4.5.6 "将被转换为 "4.5 "。用Number()进行强制类型转换, "4.5.6 "将返回NaN,因为整个字符串值不能转换成数字。如果字符串值能被完整地转换,Number()将判断是调用parseInt()方法还是调用 parseFloat()方法。下表说明了对不同的值调用Number()方法会发生的情况:

用  法 结  果 
Number(false)   0 
Number(true)   1 
Number(undefined)   NaN 
Number(null)   0 
Number( "5.5 ")   5.5 
Number( "56 ")   56 
Number( "5.6.7 ")   NaN 
Number(new   Object())   NaN 
Number(100)   100

最后一种强制类型转换方法String()是最简单的,因为它可把任何值转换成字符串。要执行这种强制类型转换,只需要调用作为参数传递进来的值的 toString()方法,即把1转换成   "1 ",把true转换成 "true ",把false转换成 "false ",依此类推。强制转换成字符串和调用toString()方法的唯一不同之处在于,对null或undefined值强制类型转换可以生成字符串而不引 发错误:

var   s1   =   String(null);   //"null" 
var   oNull   =   null; 
var   s2   =   oNull.toString();   //won’t   work,   causes   an   error

3. 利用js变量弱类型转换

举个小例子,一看,就会明白了。
<script> 
var   str= '012.345 '; 
var   x   =   str-0; 
x   =   x*1;
</script>

1、string

    var string = "this is mine"
    string.substring();            //截取函数
    string.toLowerCase();        //换换小写
    string.toUpperCase();        //转换大写
    string.indexOf("is") > -1;    //字符串检索,检索不到返回-1
    string.replace("mine","yours")    //字符串替换
    string.charCodeAt(2)                //返回第二个字符的Unicode编码
    string.fromCharCode(60)           //返回unicode 为60的字符
    encodeURI(string)                    //将字符串转换成URL编码
    decodeURI(code)                    //同上相反
    encodeURIComponent()
    decodeURIComponent()
    base64Encode()
    base64Decode()                     //base64编码转换

2、    number
    var i = 1;
    i.toString();        //数字转字符串
    i=parseInt(str)    //同上相反
    typeof i == "number"    //判断是否为数字

3.判断是否为有效的数字 
var i = 123; var str = "string"; 
if( typeof i == "number" ){ } //true

//某些方法(如:parseInt,parseFloat)会返回一个特殊的值NaN(Not a Number) 
//请注意第2点中的[注意],此方法不完全适合判断一个字符串是否是数字型!! 
i = parseInt(str); 
if( isNaN(i) ){ }

4.数字型比较 
//此知识与[字符串比较]相同

5.小数转整数 
var f = 1.5; 
var i = Math.round(f); //结果:2 (四舍五入) 
var i = Math.ceil(f); //结果:2 (返回大于f的最小整数) 
var i = Math.floor(f); //结果:1 (返回小于f的最大整数)

6.格式化显示数字 
var i = 3.14159;

//格式化为两位小数的浮点数 
var str = i.toFixed(2); //结果: "3.14"

//格式化为五位数字的浮点数(从左到右五位数字,不够补零) 
var str = i.toPrecision(5); //结果: "3.1415"

7.X进制数字的转换 
//不是很懂 -.- 
var i = parseInt("0x1f",16); 
var i = parseInt(i,10); 
var i = parseInt("11010011",2);

8.随机数 
//返回0-1之间的任意小数 
var rnd = Math.random(); 
//返回0-n之间的任意整数(不包括n) 
var rnd = Math.floor(Math.random() * n)

//-----------------------------------------------------------------------

·Math对象 
1. Math.abs(num) : 返回num的绝对值 
2. Math.acos(num) : 返回num的反余弦值 
3. Math.asin(num) : 返回num的反正弦值 
4. Math.atan(num) : 返回num的反正切值 
5. Math.atan2(y,x) : 返回y除以x的商的反正切值 
6. Math.ceil(num) : 返回大于num的最小整数 
7. Math.cos(num) : 返回num的余弦值 
8. Math.exp(x) : 返回以自然数为底,x次幂的数 
9. Math.floor(num) : 返回小于num的最大整数 
10.Math.log(num) : 返回num的自然对数 
11.Math.max(num1,num2) : 返回num1和num2中较大的一个 
12.Math.min(num1,num2) : 返回num1和num2中较小的一个 
13.Math.pow(x,y) : 返回x的y次方的值 
14.Math.random() : 返回0到1之间的一个随机数 
15.Math.round(num) : 返回num四舍五入后的值 
16.Math.sin(num) : 返回num的正弦值 
17.Math.sqrt(num) : 返回num的平方根 
18.Math.tan(num) : 返回num的正切值 
19.Math.E : 自然数(2.718281828459045) 
20.Math.LN2 : 2的自然对数(0.6931471805599453) 
21.Math.LN10 : 10的自然对数(2.302585092994046) 
22.Math.LOG2E : log 2 为底的自然数(1.4426950408889634) 
23.Math.LOG10E : log 10 为底的自然数(0.4342944819032518) 
24.Math.PI : π(3.141592653589793) 
25.Math.SQRT1_2 : 1/2的平方根(0.7071067811865476) 
26.Math.SQRT2 : 2的平方根(1.4142135623730951)

//-----------------------------------------------------------------------

·日期型(Date) 
1.声明 
var myDate = new Date(); //系统当前时间

var myDate = new Date(yyyy, mm, dd, hh, mm, ss); 
var myDate = new Date(yyyy, mm, dd); 
var myDate = new Date("monthName dd, yyyy hh:mm:ss"); 
var myDate = new Date("monthName dd, yyyy"); 
var myDate = new Date(epochMilliseconds);

2.获取时间的某部份 
var myDate = new Date(); 
myDate.getYear(); //获取当前年份(2位) 
myDate.getFullYear(); //获取完整的年份(4位,1970-????) 
myDate.getMonth(); //获取当前月份(0-11,0代表1月) 
myDate.getDate(); //获取当前日(1-31) 
myDate.getDay(); //获取当前星期X(0-6,0代表星期天) 
myDate.getTime(); //获取当前时间(从1970.1.1开始的毫秒数) 
myDate.getHours(); //获取当前小时数(0-23) 
myDate.getMinutes(); //获取当前分钟数(0-59) 
myDate.getSeconds(); //获取当前秒数(0-59) 
myDate.getMilliseconds(); //获取当前毫秒数(0-999) 
myDate.toLocaleDateString(); //获取当前日期 
myDate.toLocaleTimeString(); //获取当前时间 
myDate.toLocaleString( ); //获取日期与时间

3.计算之前或未来的时间 
var myDate = new Date(); 
myDate.setDate(myDate.getDate() + 10); //当前时间加10天 
//类似的方法都基本相同,以set开头,具体参考第2点

4.计算两个日期的偏移量 
var i = daysBetween(beginDate,endDate); //返回天数 
var i = beginDate.getTimezoneOffset(endDate); //返回分钟数

5.检查有效日期 
//checkDate() 只允许"mm-dd-yyyy"或"mm/dd/yyyy"两种格式的日期 
if( checkDate("2006-01-01") ){ }

//正则表达式(自己写的检查 yyyy-mm-dd, yy-mm-dd, yyyy/mm/dd, yy/mm/dd 四种) 
var r = /^(\d{2}|\d{4})[\/-]\d{1,2}[\/-]\d{1,2}$/; 
if( r.test( myString ) ){ }

//-----------------------------------------------------------------------

·数组(Array) 
1.声明 
var arr = new Array(); //声明一个空数组 
var arr = new Array(10); //声明一个10个长度的数组 
var arr = new Array("Alice", "Fred", "Jean"); //用值初始化数组 
var arr = ["Alice", "Fred", "Jean"]; //用值初始化数组 
var arr = [["A","B","C"][1,2,3]]; //声明一个二(多)维数组

2.数组的访问 
arr[0] = "123"; //赋值 
var str = arr[0]; //获取 
arr[0][0] = "123"; //多维数组赋值

3.数组与字符串间的转换 
var arr = ["A","B","C","D"]; //声明

//数组按分隔符转换成字符串 
var str = arr.join("|"); //结果: "A|B|C|D"

//字符串切割成数组 
arr = str.split("|");

4.遍历数组 
for( var i=0; i<arr.length; i++="" ){="" alert(arr[i]);="" }<="" span="">

5.排序 
var arr = [12,15,8,9]; 
arr.sort(); //结果: 8 9 12 15

6.组合与分解数组 
var arr1 = ["A","B","C","D"]; 
var arr2 = ["1","2","3","4"];

//奖两个数组组合成一个新的数组 
var arr = arr1.concat(arr2); //结果: ["A","B","C","D","1","2","3","4"]

//将一个数组切成两个数组(参数1:起始索引,参数2:切割长度) 
var arr3 = arr.splice(1,3); //结果: arr3:["B","C","D"] arr["A","1","2","3","4"]

//将一个数组切成两个数组,并在原数组补新值 
var arr4 = arr.splice(1,3,"AA"); //结果: arr4:["B","C","D"] arr["A","AA","1","2","3","4"]

//-----------------------------------------------------------------------

·自定义对象 
1.声明: 
function myUser(uid,pwd){ 
this.uid = uid; 
this.pwd = pwd || "000000"; //默认值 
this.show = showInfo; //方法 
}

//下面的函数不是自定义对象,是自定义对象的方法.继续看下去就明白了 
function showInfo(){ 
alert("用户名:" + this.uid + ",密码:" + this.pwd) 
}

2.实例化: 
var user = new myUser("user","123456"); 
var user = {uid:"user",pwd:"123456"};

3.获取与设置 
alert("用户名是:" + user.uid); //get 
user.uid = "newuser"; //set 
user.show(); //调用show()方法

//-----------------------------------------------------------------------

·变量 函数 流程控制 
1.变量 
var i = 1; 
var i = 1, str = "hello";

2.函数 
function funName(){ 
//do something. 

function funName(param1[,paramX]){ 
//do something. 
}

3.嵌套函数 
//某种情况,你需要创建一个函数本身所独有的函数. 
function myFunction(){ 
//do something. 
privateFunction(); 
function privateFunction(){ 
//do something. 

}

4.匿名函数 
var tmp = function(){ alert("only test."); } 
tmp();

5.延迟函数调用 
var tId = setTimeout("myFun()",1000); //延迟1000毫秒后再调用myFun()函数 
fucntion myFun(){ 
//do something 
clearTimeout(tId); //销毁对象 
}

6.流程控制 
if( condition ){ } 
if( condition ){ } else{ } 
if( condition ){ } else if( condition ){ } else{ }

switch( expression ){ 
case valA : statement; break; 
case valB : statement; break; 
default : statement; break; 
}

7.异常捕获 
try{ expression } catch(e){ } finally{ }

//不处理任何异常 
window.onerror = doNothing; 
function doNothing(){ return true; }

//异常类可用的属性 
description : 异常描述(IE,NN) 
fileName : 异常页面URI(NN) 
lineNumber : 异常行数(NN) 
message : 异常描述(IE,NN) 
name : 错误类型(IE,NN) 
number : 错误代码(IE)

//错误信息(兼容所有浏览器) 
try{ } 
catch(e){ 
var msg = (e.message) ? e.message : e.description; 
alert(msg); 
}

8.加快脚本的执行速度 
-避免使用 eval() 函数 
-避免使用 with 关键字 
-将重复的表达式赋值精简到最小 
-在较大的对象中使用索引来查找数组 
-减少 document.write() 的使用

//-----------------------------------------------------------------------

·浏览器特征( navigator ) 
1.浏览器名称 
//IE : "Microsoft Internet Explorer" 
//NS : "Netscape" 
var browserName = navigator.appName;

2.浏览器版本 
bar browserVersion = navigator.appVersion;

3.客户端操作系统 
var isWin = ( navigator.userAgent.indexOf("Win") != -1 ); 
var isMac = ( navigator.userAgent.indexOf("Mac") != -1 ); 
var isUnix = ( navigator.userAgent.indexOf("X11") != -1 );

4.判断是否支持某对象,方法,属性 
//当一个对象,方法,属性未定义时会返回undefined或null等,这些特殊值都是false 
if( document.images ){ } 
if( document.getElementById ){ }

5.检查浏览器当前语言 
if( navigator.userLanguage ){ var l = navigator.userLanguage.toUpperCase(); }

6.检查浏览器是否支持Cookies 
if( navigator.cookieEnabled ){ }

//-----------------------------------------------------------------------

·控制浏览器窗口( window ) 
1.设置浏览器的大小 
window.resizeTo(800, 600); //将浏览器调整到800X600大小 
window.resizeBy(50, -10); //在原有大小上改变增大或减小窗口大小

2.调整浏览器的位置 
window.moveTo(10, 20); //将浏览器的位置定位到X:10 Y:20 
window.moveBy(0, 10); //在原有位置上移动位置(偏移量)

3.创建一个新的窗口 
var win = window.open("about.htm","winName","height=300,width=400");

//参数 
alwaysLowered //始终在其它浏览器窗口的后面(NN) 
alwaysRaised //始终在其它浏览器窗口的前面(NN) 
channelMode //是否为导航模式(IE) 
copyhistory //复制历史记录至新开的窗口(NN) 
dependent //新窗口随打开它的主窗口关闭而关闭(NN) 
fullscreen //全屏模式(所有相关的工具栏都没有)(IE) 
location //是否显示地址栏(NN,IE) 
menubar //是否显示菜单栏(NN,IE) 
scrollbars //是否显示滚动条(NN,IE) 
status //是否显示状态栏(NN,IE) 
toolbar //是否显示工具栏(NN,IE) 
directories //是否显示链接栏(NN,IE) 
titlebar //是否显示标题栏(NN) 
hotkeys //显示菜单快捷键(NN) 
innerHeight //内容区域的高度(NN) 
innerWidth //内容区域的宽度(NN) 
resizable //是否可以调整大小(NN,IE) 
top //窗口距离桌面上边界的大小(NN,IE) 
left //窗口距离桌面左边界的大小(NN,IE) 
height //窗口高度(NN,IE) 
width //浏览器的宽度

4.与新窗口通讯 
win.focus(); //让新窗口获得焦点 
win.document.write("abc"); //在新窗口上操作 
win.document.close(); //结束流操作 
opener.close();

5.模式窗口 
window.showModalDialog("test.htm",dialogArgs,"param"); //传递对象 
window.showModelessDialog("test.htm",myFunction,"param"); //传递函数 
window.dialogArguments //对话框访问父窗口传递过来的对象 
window.returnValue //父窗口获取对话框返回的值

//参数 
center //窗口居中屏幕 
dialogHeight //窗口高度 
dialogWidth //窗口宽度 
dialogTop //窗口距离屏幕的上边距 
dialogLeft //窗口距离屏幕的左边距 
edge //边框风格(raised|sunken) 
help //显示帮助按钮 
resizable //是否可以改变窗口大小 
status //是否显示状态栏

//例子

贰、js的基础(二)类型转换的更多相关文章

  1. JS运动基础(二) 摩擦运动、缓冲运动

    摩擦运动: 逐渐变慢,最后停止 缓冲运动: 与摩擦力的区别:可以精确的停到指定目标点距离越远速度越大速度由距离决定速度=(目标值-当前值)/缩放系数Bug:速度取整值取整: iSpeed = iSpe ...

  2. 贰、js的基础(一)

    1.js的语法 a.区分大小写 b.弱类型变量:变量无特定类型 c.每行结尾的分号可有可无 d.括号用于代码块 e.注释的方法与c语言和java相同 2.变量 注意事项: a.通过关键字var来声明. ...

  3. node.js学习(二)--Node.js控制台(REPL)&&Node.js的基础和语法

    1.1.2 Node.js控制台(REPL) Node.js也有自己的虚拟的运行环境:REPL. 我们可以使用它来执行任何的Node.js或者javascript代码.还可以引入模块和使用文件系统. ...

  4. 2、JavaScript 基础二 (从零学习JavaScript)

     11.强制转换 强制转换主要指使用Number.String和Boolean三个构造函数,手动将各种类型的值,转换成数字.字符串或者布尔值. 1>Number强制转换 参数为原始类型值的转换规 ...

  5. js之数据类型及类型转换

    一.数据类型 js中的数据类型:      5种基础类型:Undefined,Null,Boolean,Number,String      1种复合类型:Object(对象包括数组,函数等)   1 ...

  6. Bootstrap <基础二十九>面板(Panels)

    Bootstrap 面板(Panels).面板组件用于把 DOM 组件插入到一个盒子中.创建一个基本的面板,只需要向 <div> 元素添加 class .panel 和 class .pa ...

  7. Bootstrap <基础二十八>列表组

    列表组.列表组件用于以列表形式呈现复杂的和自定义的内容.创建一个基本的列表组的步骤如下: 向元素 <ul> 添加 class .list-group. 向 <li> 添加 cl ...

  8. Bootstrap<基础二十七> 多媒体对象(Media Object)

    Bootstrap 中的多媒体对象(Media Object).这些抽象的对象样式用于创建各种类型的组件(比如:博客评论),我们可以在组件中使用图文混排,图像可以左对齐或者右对齐.媒体对象可以用更少的 ...

  9. Bootstrap <基础二十六>进度条

    Bootstrap 进度条.在本教程中,你将看到如何使用 Bootstrap 创建加载.重定向或动作状态的进度条. Bootstrap 进度条使用 CSS3 过渡和动画来获得该效果.Internet ...

  10. Bootstrap <基础二十五>警告(Alerts)

    警告(Alerts)以及 Bootstrap 所提供的用于警告的 class.警告(Alerts)向用户提供了一种定义消息样式的方式.它们为典型的用户操作提供了上下文信息反馈. 您可以为警告框添加一个 ...

随机推荐

  1. Python爬虫:爬取某网站关键词对应商品ID,且存入DB2数据库

    公司研发不给力,我就自己写了一个,专门爬关键词对应的商品ID. 其中还学会了用Python操作DB2数据库.Python发送邮件.写日志文件.处理浏览器访问限制. #!/usr/bin/python# ...

  2. 小数据量csv文件数据导入数据库(思路)

    大致写写思路,因为sqlserver提供了可以直接导入的图形界面. 1.private static string GetConnectionString(string folderPath)  // ...

  3. 数据库过滤操作中 != 或者 <> 指定操作数并不能改匹配到NULL值

    数据库过滤操作中 != 或者 <> 指定操作数并不能改匹配到NULL值

  4. 构造器参数过多时考虑使用构建器(Builder)

    一.静态工厂和构造器的局限性 面对需要大量可选参数才能构建对象时,静态工厂和构造器并不能随着可选参数的增加而合理扩展. 假设创建一个类Person需要使用大量的可选参数,其中两个参数是必填的,剩下的都 ...

  5. LeetCode Golang 8. 字符串转换整数 (atoi)

    8. 字符串转换整数 (atoi) 首先,该函数会根据需要丢弃无用的开头空格字符,直到寻找到第一个非空格的字符为止. 当我们寻找到的第一个非空字符为正或者负号时,则将该符号与之后面尽可能多的连续数字组 ...

  6. zabbix、agent端服务器图形化展示

    [root@agent ~]# cat /etc/hostname agent.zabbix.com [root@agent ~]# cat /etc/hosts 127.0.0.1   localh ...

  7. 10、Latent Relational Metric Learning via Memory-based Attention for Collaborative Ranking-----基于记忆注意的潜在关系度量协同排序

    一.摘要: 本文模型 LRML(潜在相关度量学习)是一种新的度量学习方法的推荐.[旨在学习用户和项目之间的相关关系,而不是简单的用户和项目之间的push和pull关系,push和pull主要针对LMN ...

  8. web自动化-selenium2入门讲解(mac版本)

    最近要做一个selenium2的分享,于是总结了下我用selenium2的感受,希望分享出来,可以对入门的小伙伴有一点帮助,也希望得到大佬的指教   一,环境搭建maven+selenium2+tes ...

  9. Spring项目配置log4j日志功能

    一,添加log4j依赖包 可从官网上下载该依赖包log4j-x.x.xx.jar,下载后 build path,添加依赖包如使用maven,可以添加如下依赖 <!-- https://mvnre ...

  10. HDU 4458 Shoot the Airplane( 判断点在多边形内外 )

    链接:传送门 题意:这个游戏是一个2D打飞机游戏,飞机以速度 v 水平飞行,它是一个简单的多边形,玩家从( 0 , 0 )向上射击,子弹有一个出速度 b ,子弹可以看作一个点,打中飞机边缘是无法击落飞 ...