累加求和
function num() {
var nul = 0,
len = arguments.length;
//因为不知道传入的参数,所有直接用arguments实参列表
//arguments是个数组,所以有length属性
for(var i = 0; i < len; i ++ ){
nul += arguments[i];
//把实参类表的第 i 位累加,达到累加器的效果
}
console.log(nul);
}
num(1,2,3,4,5);
隐式类型转换--字符串前面加“+”号,可以转换成 number 类型
function myNumber(target) {
return +target;
}
var num = myNumber('123');
console.log(typeof(num) + ":" + num);
//结果返回 number : 132 ;
//如果字符串是英文,这结果返回 number : NAN;
输入一个数字,得出反向汉字
function reverse() {
var num = window.prompt("请输入");
var str = "";
for(var i = num.length-1; i >= 0; i --) {
//也可以正向输出大写
// var i = 0; i <= num.length-1; i ++
str += reansfer(num[i]);
// 把 reansfer方法得到的汉字传到一个空字符串里累加
}
console.log(str);
}
function transfer(target) {
switch(target) {
case "0":
return "零";
case "1":
return "一";
case "2":
return "二";
case "3":
return "三";
case "4":
return "四";
case "5":
return "五";
case "6":
return "六";
case "7":
return "七";
case "8":
return "八";
case "9":
return "九";
}
}
算阶乘用的--递归
function num(n) {
if(n == 1 || n == 0) {
return 1;
}
return n * num(n-1);
}
//解析
num(5);
// num(5) ==> 5 * num(4);
// num(4) ==> 4 * num(3);
// num(3) ==> 3 * num(2);
// num(2) ==> 2 * num(1);
预编译
JS 单线程 解释性语言 解释一行执行一行
1.语法分析(先扫描看一遍,有没有错误)
2.语法解析(预编译发生在函数执行的前一刻)
3.解释一行,执行一行
暗示全局变量:
即任何变量,如果变量未经声明就赋值,此变量就为全局对象所有。一切声明的全局变量,都是(window)全局变量。
过程:
1.创建AO对象 Activation object(执行期上下文);
2.找形参和变量声明,将变量和形参名作为AO属性名,值为undefined
3.将实参值和形参统一
4.在函数体里面找函数声明,值赋予函数体;
闭包实现累加
function add() {
var count = 0;
function demo() {
count ++;
console.log(count);
}
return demo;
}
var counter = add();
counter();
counter();
counter();
counter();
立即执行函数
一经执行,立即销毁,可以有参数,带返回值
var num = (function(a,b,c){
var d = a + b + c * 2;
return d;
}(1,2,3))
函数声明 | 函数表达式 |
function test(){} | var test = function (){}() |
只有表达式才能被执行符号()执行;
使用原生JS,addEventListener,给每个li元素绑定一个click事件,并输出他们的顺序
<style>
*{
margin: 0;
padding:0;
}
ul{
list-style: none;
}
li:nth-of-type(2n){
background: red;
}
li:nth-of-type(2n+1){
background: yellow;
}
li{
text-align: center;
}
</style>
<ul>
<li>a</li>
<li>a</li>
<li>a</li>
<li>a</li>
</ul>
function test() {
var liList = document.getElementsByTagName('li');
for(var i = 0; i < liList.length; i ++) {
(function(j){
liList[j].onclick = function () {
console.log(j);
}
}(i))
}
}
test();
用 charCodeAt 方法计算一个字符串的字符长度
function num(target) {
var count = 0;
for(var i = 0; i < target.length; i ++) {
if(target.charCodeAt(i) <= 255) {
// Unicode 编码前255位都占一个位,255后面站2个
count ++;
}else if(target.charCodeAt > 255) {
count += 2;
}
}
console.log(count);
}
,逗号操作符 会把后面计算结果返回出去
var f=(
function f() {
return "1";
},
function g() {
return 2;
}
)();
typeof f;
// 返回 数字2,所有typeof f 为 unmber
立即执行函数,函数名消失问题
var x = 1;
if(function f() {}) {
//在括号里就会 函数声明就会变成表达式,变成表达式f 就消失了
x += typeof f;
// 未经声明就使用的变量,放到typeof里不会报错 返回undefined,是字符串类型
}
x; // 1undefined
构造函数,内部this隐式转换
1.预编译 this -- > window
2.谁调用的 this 指向谁
3.call apply
4.全局 this -- > window
var a = 5;
function test() {
a = 0;
alert(a);
alert(this.a);
var a;
alert(a);
}
test(); // 0 5 0
new test(); // 0 undefined 0
// new 一下就会出现3部内部转换
// 1.var this = Object.create(test.prototype)
// 2.然后添加上this的属性
// 3.return this
// Object.create(test.prototype)上没有a所以 打印undefined
包装类
原始值跟引用值的储存空间不同,原始值储存在栈内存中,不能有属性和方法,在调用属性时,
他会隐式的发生一个过程 new一个Number,随后立即 删除.
var str = "abc";
// new String('abc').length; delete
//原始值没有属性方法,当调用他的方法时,内部会产生包装类
//使得str = "abc",会在内部转化成 对象字符串方法new String("arc");
//所以可以访问到length属性;
console.log(str.length)
判断字符串字节长度
var str = "abcd李白";
//1.把字符串长度全部按小于255字节算,然后查询到每有一个大于255的,就加一
function strLength(str) {
var count = str.length;
for(var i = 0; i < str.length; i ++) {
if(str.charCodeAt(i) > 255) {
count ++;
}
}
return count;
}
//2.创建一个空容器,然后判断每个字符串字节,小于255 加1,大于255 加2
function strLength(str) {
var count = 0;
for(var i = 0; i < str.length; i ++) {
if(str.charCodeAt(i) > 255){
count += 2;
}else{
count ++;
}
}
return count;
}
call--apply
call | apply | |
不同点 | 需要把实参按照形参的个数传进去 |
需要传一个arguments 数组 |
相同点 | 改变this指向 | 改变this指向 |
圣杯模式
var inherit = (function () {
var F = function(){};
return funtion(Target,Origin){
F.prototype = Origin.prototype;
Target.prototype = new F();
Target.prototype.constructor = Target;
Target.prototype.uber = Origin.prototype;
}
}());
for in 循环
遍历 枚举 对象用的,for in 循环,因为不知道对象的length所以用for in
如果是手动设置的原型上的值都可以打印,系统自带的不能打印
遍历属性想获取对象里面的值要写成方括号形式obj[prop];
如果不想获取到原型上的属性要使用hasOwnproperty方法
in 操作符,是能不能再对象上调用这个属性,原型上的也算。
var obj = {
name : "li",
age : "123",
sex : "male",
height : 123,
__proto__ : {
lastName : "bai"
}
}
for(var prop in obj) {
if(obj.hasOwnproperty(prop)) {//不获取原型上的属性
console.log(obj[prop]);
}
}
instanceof操作符
A instanceof B
看A对象的原型链上有没有B的原型
var person = new Person();
person instanceof Person
区别数组和对象的方法{}[]
var arr = [];
var obj = {};
1.用 constructor
[].constructor 会输出 function Array(){[native code]}
obj.constructor 会输出 function Object(){[native code]}
2.用 instanceof
[] instanceof Array 会输出 true
obj instanceof Array 会输出 false
3.用 call toString (各种构造函数都重写了 toString方法) 用这个好
Object.prototype.toString.call([]); 输出 array
Object.prototype.toString.call({}); 输出 object
Object.prototype.toString.call(123); 输出 number;
typeof 返回值
特殊:空值传到typeof里 会返回 undefined , null 会返回 object , undefined 会返回 undefined , [] {} 会返回object ,
Array , Object 会返回 function
正常返回 :
number string boolean object undefined function
普通克隆模式
针对于没有引用值的克隆
var obj = {
name : "abc",
age : 12,
sex : "male",
card : ["visa","un"]
}
var obj1 = {};
function kelong(origin,target) {
var target = target || {};
for(var prop in origin){
if(origin.hasOwnproperty(prop)){
target[prop] = origin[prop]
}
}
return target;
}
kelong(obj,obj1);
深层克隆模式
遍历对象 for(var prop in obj)
1.判断是不是原始值 typeof() object
2.判断是数组还是对象 instanceof constructor toString
3.建立了相应的数组或对象
4.递归
var obj = {
name : "abc",
age : 12,
sex : "male",
car : {
num :"123",
qwe :{
er : "df",
ter : "dssd"
}
}
}
function deepClone(origin,target) {
var target = target || {},
toStr = Object.prototype.toString,
arrStr = "[object Array]";
for(var prop in origin) {
if(origin.hasOwnproperty(prop)){
if(origin[prop] !== "null" && typeof(origin[prop]) == 'object') {
target[prop] = toStr.call(origin[prop]) == arrStr ? [] : {};
deepClone(origin[prop],target[prop]);
}else{
target[prop] = origin[prop];
}
}
}
return target;
}
deepClone();
数组
var arr = []; 数组自变量 优先使用 | var arr = new Array(); |
传的参数是数组内的内容 | 传的参数表示数组的长度 |
改变数组的几种方法
push , pop , shift , unshift , sort , reverse , splice
不改变原数组
concat , join , split , toString , slice
push方法原理
var arr = [1,2,3];
Array.prototype.push = function () {
for(var i = 0; i < arguments.length; i ++) {
this[this.length] = arguments[i];
}
return this.length;
}
给数组升序,降序
var arr = [10,2,9,13,4,8,9];
arr.sort(function(a,b){
return a - b; //升序
return b - a; //降序
})
给一个有序数组乱序
var arr = [1,2,3,4,5,6];
arr.sort(function(){
return Math.random() - 0.5;
})
类数组
属性要为索引(数字)属性,必须有length属性,最好加上push
类数组赋值例子:
var obj = {
"2" : 'b',
"3" : 'c',
"length" : 2,
"push" : Array.prototype.push
}
obj.push('a');
obj.push('d');
//push 内部原理是根据length改变的
// 先把长度赋值,然后长度++
Array.prototype.push = function (target) [
obj[obj.length] = target;
obj.length ++;
}
封装type方法
function type(target) {
var template = {
"[object Array]" : "array",
"[object Object]" : "object",
"[object Number]" : "number - object",
"[object Boolean]" : "boolean - object",
"[object String]" : "string - object"
};
if(target == null) {
return "null";
}
if(typeof(target) == 'object') {
var str = Object.prototype.toString.call(target);
return template[str];
}else{
return typeof(target);
}
}
// 先判断是否是 null类型
// 判断是不是object对象类型,如果是 在用toString.call()方法判断引用值,然后输出
// 剩下的原始值直接typeof判断
原型链上数组去重
var arr = [1,2,1,2,3,3,5,5,4,2,1,6,2,6,5];
Array.prototype.unique = function () {
var temp = {}, //接收数组内容
arr = [], //要返回的新数组
len = this.length;
for(var i = 0; i < len; i ++) {
if(!temp[this[i]]){ //取类数组没有赋值的位
temp[this[i]] = 'abc';
arr.push(this[i]);
}
}
return arr;
}
在数组中取出重复的数
原理:
将传入的数组arr中的每一个元素value当作另外一个新数组b的key, 然后遍历arr去访问b[value],
若b[value] 不存在, 则将b[value] 设置为1, 若b[value] 存在, 则将其加1。 可以想象,
若arr中数组没有重复的元素, 则b数组中所有元素均为1; 若arr数组中存在重复的元素, 则在第二次访问该b[value] 时, b[value] 会加1, 其值就为2了。 最后遍历b数组, 将其值大于1的元素的key存入另一个数组a中, 就得到了arr中重复的元素。
var arr = [1,2,3,4,5,6,7,8,9,1,2,1,1,5,4,45,45,5,5,45,10];
function duplicates(arr){
//声明两个数组,a数组用来存放结果,b数组用来存放arr中每个元素的个数
var a = [],
b = [];
//遍历arr,如果以arr中元素为下标的的b元素已存在,则该b元素加1,否则设置为1
for(var i = 0; i < arr.length; i ++) {
if(!b[arr[i]]){
b[arr[i]] = 1;
continue;
}
b[arr[i]] ++;
}
//遍历b数组,将其中元素值大于1的元素下标存入a数组中
for(var i = 0; i < b.length; i ++){
if(b[i] > 1){
a.push(i);
}
}
return a;
}
try......catch 防错
try{
console.log('a');
console.log(b); //如果遇到出错,不会往下执行try里的语句
console.log('c');
}catch(e){
console.log(e.name + " : " + e.message);//会把错误报出来
}