从0学习javascript

JavaScriptCore

JSStringCreateWithUTF8CString 将 C 字符串转换为 JavaScript 字符串
JSEvaluateScript

JSContextGroupCreate();
JSGlobalContextCreateInGroup();
JSValueToNumber();

html中
由包含的代码就是JavaScript代码,它将直接被浏览器执行

在同一个页面中引入多个.js文件,还可以在页面中多次编写,浏览器按照顺序依次执行。

JavaScript的Number不区分整数和浮点数

第一种是==比较,它会自动转换数据类型再比较,很多时候,会得到非常诡异的结果;

第二种是===比较,它不会自动转换数据类型,如果数据类型不一致,返回false,如果一致,再比较。

NaN === NaN; // false

JavaScript的数组可以包括任意数据类型

动态语言 var & 不使用var(全局变量)

如果一个变量没有通过var申明就被使用,那么该变量就自动被申明为全局变量:

var申明的变量则不是全局变量,它的范围被限制在该变量被申明的函数体内

用反引号表示多行字符串

字符串是不可变的,如果对字符串的某个索引赋值,不会有任何错误,但是,也没有任何效果
var s = ‘Test’;
s[0] = ‘X’;
alert(s); // s仍然为’Test’

但给Array的length赋一个新的值会导致Array大小的变化也可以通过索引把对应的元素修改为新的值,此时如果索引超过了范围,同样会引起Array大小的变化
也支持 push pop # 末尾添加删除
unshift shift # 开头添加删除
注意这里与python中队列不同
splice()方法是修改Array的“万能方法”,它可以从指定的索引开始删除若干元素,然后再从该位置添加若干元素:返回删除的元素
concat
join()方法是一个非常实用的方法,它把当前Array的每个元素都用指定的字符串连接起来,然后返回连接后的字符串
var arr = [‘A’, ‘B’, ‘C’, 1, 2, 3];
arr.join(‘-’); // ‘A-B-C-1-2-3’
arr.slice(0, 3) 左闭右开
array直接转字符串带,

undefined & null

判断一个属性是否是对象自身拥有的,而不是继承得到的,可以用hasOwnProperty()方法

for ( ; ; )
for (var x in xx) 遍历的实际上是对象的属性名称
例如 a = [‘A’, ‘B’, ‘C’] -> 0 1 2 + a.name = ‘Hello’ -> 0 1 2 ‘name’
两个用of 都是 ‘A’ ‘B’ ’C’

for of
while & do while

forEach
a.forEach(function (element, index, array) {
// element: 指向当前元素的值
// index: 指向当前索引
// array: 指向对象本身
console.log(element + ', index = ’ + index);
});

也可以只用某个:
a.forEach(function (element) {
console.log(element);
});

var arr = [‘Apple’, ‘pear’, ‘orange’];
arr.forEach(console.log); // 依次打印每个元素

{} 必
须是字符串
Map 支持 Number作为键 ( new Map() ).get .set
Set 不存储value( new Set() )

可以有名或者匿名
function abs(x) {
if (x >= 0) {
return x;
} else {
return -x;
}
}(这里没有分号)
var abs = function (x) {
if (x >= 0) {
return x;
} else {
return -x;
}
};(这里有分号)

箭头函数相当于匿名函数,并且简化了函数定义。箭头函数有两种格式,一种像上面的,只包含一个表达式,连{ … }和return都省略掉了。还有一种可以包含多条语句,这时候就不能省略{ … }和return:

x => {
if (x > 0) {
return x * x;
}
else {
return - x * x;
}
}
// 两个参数:
(x, y) => x * x + y * y

// 无参数:
() => 3.14

// 可变参数:
(x, y, …rest) => {
var i, sum = x + y;
for (i=0; i<rest.length; i++) {
sum += rest[i];
}
return sum;
}

JavaScript允许传入任意个参数而不影响调用,因此传入的参数比定义的参数多也没有问题
传入的参数比定义的少也没有问题:
abs(); // 返回NaN
此时abs(x)函数的参数x将收到undefined,计算结果为NaN。

关键字arguments,它只在函数内部起作用,并且永远指向当前函数的调用者传入的所有参数。arguments类似Array但它不是一个Array

function abs() {
if (arguments.length === 0) {
return 0;
}
var x = arguments[0];
return x >= 0 ? x : -x;
}

rest参数,前面用…标识,接受多余参数function foo(a, b, …rest) {
console.log('a = ’ + a);
console.log('b = ’ + b);
console.log(rest);
}

foo(1, 2, 3, 4, 5);
// 结果:
// a = 1
// b = 2
// Array [ 3, 4, 5 ]

JavaScript引擎在行末自动添加分号
return
3
实际上是return undefined;

JavaScript引擎会自动提升了变量的声明,但不会提升变量的赋值。

默认有一个全局对象window,全局作用域的变量实际上被绑定到window的一个属性
因此,许多库都会自己定义一个唯一的全局变量,将所有变量和函数绑定到上面

var MYAPP = {};

// 其他变量:
MYAPP.name = ‘myapp’;
MYAPP.version = 1.0;

// 其他函数:
MYAPP.foo = function () {
return ‘foo’;
};

let替代var可以申明一个块级作用域的变量(因为之前说的会提升变量声明),这样在for循环语句块就可以定义局部作用域的变量

const来定义常量,const与let都具有块级作用域

解构赋值
var [x, y, z] = [‘hello’, ‘JavaScript’, ‘ES6’];
可以截断(忽略后面未赋值的或者匿名)
let [ , , z] = [‘A’, ‘B’, ‘C’] or let [a, b] = [‘A’, ‘B’, ‘C’]

var person = {
name: ‘小明’,
age: 20,
gender: ‘male’,
passport: ‘G-12345678’,
school: ‘No.4 middle school’,
address: {
city: ‘Beijing’,
street: ‘No.1 Road’,
zipcode: ‘100001’
}
};
var {name, address: {city, zip}} = person;
name; // ‘小明’
city; // ‘Beijing’
zip; // undefined, 因为属性名是zipcode而不是zip
// 注意: address不是变量,而是为了让city和zip获得嵌套的address对象的属性:
address; // Uncaught ReferenceError: address is not defined

// 如果person对象没有single属性,默认赋值为true:
var {name, single=true} = person;
name; // ‘小明’
single; // true

如果变量已经被声明了,那需要用括号将语句括起来,否则引擎会认为{}是个块

var x, y;
({x, y} = { name: ‘小明’, x: 100, y: 200});

解构赋值是用旧值
var x=1, y=2;
[x, y] = [y, x] 交换变量

以对象的方法形式调用,比如xiaoming.age(),该函数的this指向被调用的对象,也就是xiaoming,这是符合我们预期的。

如果单独调用函数,比如getAge(),此时,该函数的this指向全局对象,也就是window
var fn = xiaoming.age; // 先拿到xiaoming的age函数
fn(); // NaN
要保证this指向正确,必须用obj.xxx()的形式调用

但箭头函数内部的this是词法作用域,由上下文确定。
var obj = {
birth: 1990,
getAge: function () {
var b = this.birth; // 1990
var fn = function () {
return new Date().getFullYear() - this.birth; // this指向window或undefined
};
return fn();
}
};
现在,箭头函数完全修复了this的指向,this总是指向词法作用域,也就是外层调用者obj:

var obj = {
birth: 1990,
getAge: function () {
var b = this.birth; // 1990
var fn = () => new Date().getFullYear() - this.birth; // this指向obj对象
return fn();
}
};
obj.getAge(); // 25

函数本身的apply方法,它接收两个参数,第一个参数就是需要绑定的this变量,第二个参数是Array,表示函数本身的参数
getAge.apply(xiaoming, []); // 25, this指向xiaoming, 参数为空

call 类似,按顺序传入参数
Math.max.apply(null, [3, 5, 4]); // 5
Math.max.call(null, 3, 5, 4); // 5

利用apply(),我们还可以动态改变函数的行为。

JavaScript的所有对象都是动态的,即使内置的函数,我们也可以重新指向新的函数。

现在假定我们想统计一下代码一共调用了多少次parseInt(),可以把所有的调用都找出来,然后手动加上count += 1,不过这样做太傻了。最佳方案是用我们自己的函数替换掉默认的parseInt():

‘use strict’;
var count = 0;
var oldParseInt = parseInt; // 保存原函数
window.parseInt = function () {
count += 1;
return oldParseInt.apply(null, arguments); // 调用原函数
};

arr.map(pow);
对arr里的对象全都应用pow函数
var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];
arr.map(String); // [‘1’, ‘2’, ‘3’, ‘4’, ‘5’, ‘6’, ‘7’, ‘8’, ‘9’]

Array的reduce()把一个函数作用在这个Array的[x1, x2, x3…]上,这个函数必须接收两个参数,reduce()把结果继续和序列的下一个元素做累积计算,其效果就是:

[x1, x2, x3, x4].reduce(f) <=> f(f(f(x1, x2), x3), x4)
var arr = [1, 3, 5, 7, 9];
arr.reduce(function (x, y) {
return x + y;
}); // 25

filter也是一个常用的操作,它用于把Array的某些元素过滤掉,然后返回剩下的元素
var arr = [1, 2, 4, 5, 6, 9, 10, 15];
var r = arr.filter(function (x) {
return x % 2 !== 0;
});
r; // [1, 5, 9, 15]
r = arr.filter(function (element, index, self) {
return self.indexOf(element) === index;
});

arr.sort(cmp) cmp是排序函数
会直接对Array进行修改

find()方法用于查找符合条件的第一个元素,如果找到了,返回这个元素,否则,返回undefined

var arr = [‘Apple’, ‘pear’, ‘orange’];
console.log(arr.find(function (s) {
return s.toLowerCase() === s;
})); // ‘pear’, 因为pear全部是小写

findindex类似,但返回索引

function lazy_sum(arr) {
var sum = function () {
return arr.reduce(function (x, y) {
return x + y;
});
}
return sum;
}
当我们调用lazy_sum()时,返回的并不是求和结果,而是求和函数:

var f = lazy_sum([1, 2, 3, 4, 5]); // function sum()
调用函数f时,才真正计算求和的结果:

f(); // 15

返回函数不要引用任何循环变量,或者后续会发生变化的变量
function count() {
var arr = [];
for (var i=1; i<=3; i++) {
arr.push(function () {
return i * i;
});
}
return arr;
}

var results = count();
var f1 = results[0];
var f2 = results[1];
var f3 = results[2];
都是16

function count() {
var arr = [];
for (var i=1; i<=3; i++) {
arr.push((function (n) {
return function () {
return n * n;
}
})(i));
}
return arr;
}

var results = count();
var f1 = results[0];
var f2 = results[1];
var f3 = results[2];

f1(); // 1
f2(); // 4
f3(); // 9

借助闭包,可以封装一个私有变量。我们用JavaScript创建一个计数器:

‘use strict’;

function create_counter(initial) {
var x = initial || 0;
return {
inc: function () {
x += 1;
return x;
}
}
}

还可以把多参数的函数变成单参数的函数

const email = “test@example.com”;
const password = ‘hello123’;

function sql(strings, …exps) {
console.log(SQL: ${strings.join('?')});
console.log(SQL parameters: ${JSON.stringify(exps)});
return {
name: ‘小明’,
age: 20
};
}

const result = sqlSELECT * FROM users WHERE email=${email} AND password=${password};

console.log(JSON.stringify(result));

SQL: SELECT * FROM users WHERE email=? AND password=?
SQL parameters: [“test@example.com”,“hello123”]
{“name”:“小明”,“age”:20}

sqlxxx即是标签函数 会自动转换为对sql()函数的调用
其传入参数是 除模板字符串外的字符,模板的各个值

  • 6
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值